Страница 1 из 1

Программное создание ярлыков.

Добавлено: 13 фев 2011, 20:50
StIX
Всем доброго времени суток! Я новичок в программировании, поэтому прошу Вашей помощи. Есть задача: Создать ярлык на рабочем столе ( не ярлык интернета ).
Перерыл множесво сайтов, но ничего толкового не нашел, код не как нехочет работать, наверно это из-за недостатка опыта.
Есть данный код:

Код: Выделить всё

#include <shlobj.h>
#include <string.h>

HRESULT CreateLink (LPCSTR lpszPathObj, LPCSTR lpszPathLink,
                    LPCSTR lpszDesc)
{
  HRESULT hres;
  IShellLink *psl;

  // Получить указатель на интерфейс IShellLink
  hres = CoCreateInstance (CLSID_ShellLink, NULL,
                           CLSCTX_INPROC_SERVER,
                           IID_IShellLink, (LPVOID *) &psl);
  if (SUCCEEDED (hres))
  {
    IPersistFile *ppf;

    // Установить путь к ярлыку и добавить описание
    psl->SetPath (lpszPathObj);
    psl->SetDescription (lpszDesc);

    // Преобразовать IShellLink в IPersistFile для сохранения ярлыка
    hres = psl->QueryInterface (IID_IPersistFile, (LPVOID *) &ppf);

    if (SUCCEEDED (hres))
    {
      WCHAR wsz[MAX_PATH];

      // Преобразовать строку в Unicode
      MultiByteToWideChar (CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH);

      // Сохранить ярлык вызовом IPersistFile::Save.
      hres = ppf->Save (wsz, TRUE);
      ppf->Release ();
    }
    psl->Release ();
  }
  return hres;
}

int main (int argc, char *argv[])
{
  LPITEMIDLIST P;
  char szLink[512] = "";
  // Инициализация библиотеки COM
  CoInitialize (NULL);
  // Получить путь к Рабочему столу
  if (SHGetSpecialFolderLocation (NULL, CSIDL_DESKTOP, &P) == NOERROR)
  {
    // Преобразовать путь к строке
    SHGetPathFromIDList (P, szLink);
    strcat (szLink, "\\Program.lnk");
    // Создать ярлык
    CreateLink (argv[0], szLink, "Link");
  }
  // Закрытие библиотеки COM
  CoUninitialize ();
  return 0;
}
При компиляции выдает ошибки:

Код: Выделить всё

C:\Users\admin\Documents\link.o:link.cpp|| undefined reference to `CoCreateInstance@20'|
C:\Users\admin\Documents\link.o:link.cpp|| undefined reference to `IID_IPersistFile'|
C:\Users\admin\Documents\link.o:link.cpp|| undefined reference to `CoInitialize@4'|
C:\Users\admin\Documents\link.o:link.cpp|| undefined reference to `CoUninitialize@0'|
||=== Build finished: 4 errors, 0 warnings ===|
Код взят из этой статьи.
Работаю в Code::Blocks 10.05, в Dev C++ также не работает.
Помогите пожалуйста разобраться. :) Заранее благодарен. :)

Re: Программное создание ярлыков.

Добавлено: 13 фев 2011, 21:34
WinMain
Пример создания ярлыка на рабочем столе уже приводился на этом форуме. Вот посмотри...
http://forum.developing.ru/showthread.php/12374

Re: Программное создание ярлыков.

Добавлено: 14 фев 2011, 01:10
StIX
Спасибо конечно, но это немного не то. Тот пример, что там приведен, он под Visual Studio. Я в Visual Studio не работаю, пишу консольные приложения только на "Си", учусь вернее. Хотелось бы узнать, что не верно в том коде, что я написал выше. Или не могли бы Вы привести рабочий пример под "Си" ?

Re: Программное создание ярлыков.

Добавлено: 14 фев 2011, 16:53
BulldozerBSG
А компилятор какой используешь?

Re: Программное создание ярлыков.

Добавлено: 14 фев 2011, 17:18
StIX
Компилятор который в Code::Blocks по умолчанию. GCC 4.4.1 (MingW).

Re: Программное создание ярлыков.

Добавлено: 16 фев 2011, 15:14
BulldozerBSG
по поводу твоей ошибки. Необходимо подключить либы (по моему ole32, shell32) точно как они называются не помню.
Еще под виндовс и чистый С могу посоветовать использовать Pelles C компилятор (там же и IDE). С ним проще...

Re: Программное создание ярлыков.

Добавлено: 17 фев 2011, 14:31
StIX
Вобщем проблема решена, в Visual Studio код из первого поста компилируется и работает без проблем. Насчет Pelles C, посмотрел, думаю останусь на Code::Blocks. Тем более если прикрутить к нему компилятор от Visual Studio.
Еще есть вопрос по этому коду:

Код: Выделить всё

#include <objidl.h>
#include <shlobj.h>
//...
//---------------------------------------------------------------------
#define HOTKEY(modifier,key) ((((modifier)&0xff)<<8)|((key)&0xff)) 
//--------------------------------------------------------------------- 
// Создание ярлыка 
// Входные параметры: 
//  pwzShortCutFileName - путь и имя ярлыка, например, "C:\\Блокнот.lnk" 
//    Если не указан путь, ярлык будет создан в папке, указанной в следующем параметре. 
//    Прим.: Windows сама НЕ добавляет к имени расширение .lnk 
//  pszPathAndFileName  - путь и имя программы/файла, например, "C:\\Windows\\NotePad.Exe"
//    или "C:\\Мои документы\\Файл.doc"
//  pszWorkingDirectory - рабочий каталог, например, "C:\\Windows" 
//  pszArguments        - аргументы командной строки, например, "C:\\Doc\\Text.Txt" 
//  wHotKey             - горячая клавиша, например, 
//     для Ctrl+Alt+A     HOTKEY(HOTKEYF_ALT|HOTKEYF_CONTROL,'A') 
//  iCmdShow            - начальный вид, например, SW_SHOWNORMAL.
//    Полный список - см. параметр nCmdShow функции ShowWindow 
//  pszIconFileName     - путь и имя файла, содержащего иконку, например, "C:\\Windows\\NotePad.Exe" 
//  int iIconIndex      - индекс иконки в файле, нумеруется с 0
// Возвращаемое значение:
//  успешность создания ярлыка ( true - ярлык создан; false - ошибка )
bool CreateShortcut(LPCWSTR pwzShortCutFileName, 
                   LPCTSTR pszPathAndFileName, 
                   LPCTSTR pszWorkingDirectory, 
                   LPCTSTR pszArguments, 
                   WORD wHotKey, 
                   int iCmdShow, 
                   LPCTSTR pszIconFileName, 
                   int iIconIndex) { 
  IShellLink * pSL;    /* будущий ярлык                                    */ 
  IPersistFile * pPF;  /* файл, в котором параметры ярлыка будут храниться */
  HRESULT hRes; 
  // Создание экземпляра компонента "Ярлык" 
  hRes = CoCreateInstance(CLSID_ShellLink,0,CLSCTX_INPROC_SERVER,IID_IShellLink,(LPVOID*)&pSL); 
  if( SUCCEEDED(hRes) ) { 
     hRes = pSL->SetPath(pszPathAndFileName); 
     if( SUCCEEDED(hRes) ) { 
        hRes = pSL->SetArguments(pszArguments); 
        if( SUCCEEDED(hRes) ) { 
           hRes = pSL->SetWorkingDirectory(pszWorkingDirectory); 
           if( SUCCEEDED(hRes) ) { 
              hRes = pSL->SetIconLocation(pszIconFileName,iIconIndex); 
              if( SUCCEEDED(hRes) ) { 
                 hRes = pSL->SetHotkey(wHotKey); 
                 if( SUCCEEDED(hRes) ) { 
                    hRes = pSL->SetShowCmd(iCmdShow); 
                    if( SUCCEEDED(hRes) ) { 
                       // Получение компонента хранилища параметров 
                       hRes = pSL->QueryInterface(IID_IPersistFile,(LPVOID*)&pPF); 
                       if( SUCCEEDED(hRes) ) { 
                          // Сохранение созданного ярлыка 
                          hRes = pPF->Save(pwzShortCutFileName,TRUE); 
                          pPF->Release(); 
                       } 
                    } 
                 } 
              } 
           } 
        } 
     } 
     pSL->Release(); 
  } 
  return SUCCEEDED(hRes); 
}

Код: Выделить всё

if( SUCCEEDED(hRes) )
Зачем делать 10 раз проверку одного и того же ? Да еще и вложено.

Может быть так можно?

Код: Выделить всё

  hRes = CoCreateInstance(CLSID_ShellLink,0,CLSCTX_INPROC_SERVER,IID_IShellLink,(LPVOID*)&pSL); 
  if( SUCCEEDED(hRes) ) { 
     hRes = pSL->SetPath(pszPathAndFileName); 
	 hRes = pSL->SetArguments(pszArguments); 
	 hRes = pSL->SetWorkingDirectory(pszWorkingDirectory); 
	 hRes = pSL->SetIconLocation(pszIconFileName,iIconIndex); 
	 hRes = pSL->SetHotkey(wHotKey); 
	 hRes = pSL->SetShowCmd(iCmdShow); 
	 hRes = pSL->QueryInterface(IID_IPersistFile,(LPVOID*)&pPF);
	 hRes = pPF->Save(pwzShortCutFileName,TRUE); 
	 pPF->Release(); 
	 pSL->Release(); 
	 }

Re: Программное создание ярлыков.

Добавлено: 17 фев 2011, 16:05
BulldozerBSG
У тебя каждая функция возвращает результат, вот его и проверяют

Re: Программное создание ярлыков.

Добавлено: 18 фев 2011, 18:08
StIX
Все ясно, спасибо.