こちらの記事を参考にして、ショートカットを作るプログラムを作成したのですがエラーがでます。
http://dixq.net/forum/viewtopic.php?f=3&t=6193
やりたい事は、キーボードから入力された文字列を型に格納し、「https://www.google.co.jp/search?q=」のあとに付けたショートカットの作成です。
ですが以下のコードを実行すると、TEXTの部分で ";"が必要です とエラーがでてきます。
どうすればいいのでしょうか。
また、このプログラムではデスクトップかスタートメニューにしかショートカットが作成できませんが、指定したパスに作成するにはどうすればいいのでしょうか。
#define _CRT_SECURE_NO_WARNINGS
#include <shlobj.h>
#include <iostream>
using namespace std;
int main(void)
{
char A;//型の宣言
cin >> A;//型に格納
LPCTSTR programPath = TEXT("https://www.google.co.jp/search?q=" A); // URL&A
wchar_t linkPath[MAX_PATH]; // ショートカット名はユニコード限定
// デスクトップフォルダ取得(デスクトップかスタートメニューにしか作れない)
LPITEMIDLIST pidl;
SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, &pidl);
SHGetPathFromIDListW(pidl, linkPath);
wcscat(linkPath, L"\\URL.lnk");
IShellLink* sl;
IPersistFile* pf;
CoInitialize(NULL); // COMライブラリを初期化
if (CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&sl) == S_OK)
{
if (sl->QueryInterface(IID_IPersistFile,(void **)&pf) == S_OK)
{
sl->SetPath(programPath); // プログラムパス
sl->SetDescription(NULL); // 説明(= ツールチップス)
sl->SetArguments(NULL); // コマンドライン引数
sl->SetWorkingDirectory(NULL); // 作業ディレクトリ
sl->SetIconLocation(NULL, 0); // Iconのパスまたはインデックス
sl->SetShowCmd(SW_SHOWNORMAL); // 起動時のウィンドウ表示
pf->Save(linkPath, TRUE); // ショートカットを保存
pf->Release(); // IPersistFileへのポインタを破棄
pf = NULL;
}
sl->Release(); // IShellLinkへのポインタを破棄
sl = NULL;
}
CoUninitialize (); // COMライブラリをクローズ
return 0;
}
まだ始めて一ヶ月ちょっとですので、詳しい説明やコードがあると助かります。
ショートカットの作成
Re: ショートカットの作成
コードはBBcodeを有効にした状態でcodeタグで囲み、かつ適切なインデントをしていただけると、見やすくて助かります。
言語が明示されていないようですが、cinが利用されていることなどからC++と仮定します。yosuke.25_u さんが書きました:やりたい事は、キーボードから入力された文字列を型に格納し、「https://www.google.co.jp/search?q=」のあとに付けたショートカットの作成です。
ですが以下のコードを実行すると、TEXTの部分で ";"が必要です とエラーがでてきます。
どうすればいいのでしょうか。
- C++はawkと違い、文字列を並べただけでは結合できません。
- char型は1文字(1バイト?)しか格納できないので、一般の「文字列」は格納できません。
#define _CRT_SECURE_NO_WARNINGS
#include <shlobj.h>
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string A;//型の宣言
getline(cin, A);//型に格納
string programPathData = string("https://www.google.co.jp/search?q=") + A;
const char* programPath = programPathData.c_str(); // URL&A
wchar_t linkPath[MAX_PATH]; // ショートカット名はユニコード限定
// デスクトップフォルダ取得(デスクトップかスタートメニューにしか作れない)
LPITEMIDLIST pidl;
SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, &pidl);
SHGetPathFromIDListW(pidl, linkPath);
wcscat(linkPath, L"\\URL.lnk");
IShellLinkA* sl;
IPersistFile* pf;
CoInitialize(NULL); // COMライブラリを初期化
if (CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&sl) == S_OK)
{
if (sl->QueryInterface(IID_IPersistFile,(void **)&pf) == S_OK)
{
sl->SetPath(programPath); // プログラムパス
sl->SetDescription(NULL); // 説明(= ツールチップス)
sl->SetArguments(NULL); // コマンドライン引数
sl->SetWorkingDirectory(NULL); // 作業ディレクトリ
sl->SetIconLocation(NULL, 0); // Iconのパスまたはインデックス
sl->SetShowCmd(SW_SHOWNORMAL); // 起動時のウィンドウ表示
pf->Save(linkPath, TRUE); // ショートカットを保存
pf->Release(); // IPersistFileへのポインタを破棄
pf = NULL;
}
sl->Release(); // IShellLinkへのポインタを破棄
sl = NULL;
}
CoUninitialize(); // COMライブラリをクローズ
return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: ショートカットの作成
一旦デスクトップに作成し、MoveFileW()で移動するというのはどうでしょうか?yosuke.25_u さんが書きました:また、このプログラムではデスクトップかスタートメニューにしかショートカットが作成できませんが、指定したパスに作成するにはどうすればいいのでしょうか。
#define _CRT_SECURE_NO_WARNINGS
#include <shlobj.h>
#include <rpc.h>
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string A;//型の宣言
getline(cin, A);//型に格納
string programPathData = string("https://www.google.co.jp/search?q=") + A;
const char* programPath = programPathData.c_str(); // URL&A
wchar_t linkPath[MAX_PATH]; // ショートカット名はユニコード限定
// デスクトップフォルダ取得(デスクトップかスタートメニューにしか作れない)
LPITEMIDLIST pidl;
SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, &pidl);
SHGetPathFromIDListW(pidl, linkPath);
// かぶりにくいように、UUIDでファイル名を決める
UUID uuid;
unsigned char *uuid_str;
wchar_t uuid_unicode[64];
UuidCreate(&uuid);
UuidToStringA(&uuid, &uuid_str);
if(MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (const char *)uuid_str, -1, uuid_unicode, sizeof(uuid_unicode)) == 0)
{
int code = GetLastError();
cout << "MultiByteToWideChar() error code = " << code << endl;
return 1;
}
RpcStringFreeA(&uuid_str);
wcscat(linkPath, L"\\");
wcscat(linkPath, uuid_unicode);
wcscat(linkPath, L".lnk");
// 本当にショートカットを作りたい場所
const wchar_t *actualLinkPath = L"D:\\test.lnk";
IShellLinkA* sl;
IPersistFile* pf;
CoInitialize(NULL); // COMライブラリを初期化
if (CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&sl) == S_OK)
{
if (sl->QueryInterface(IID_IPersistFile,(void **)&pf) == S_OK)
{
sl->SetPath(programPath); // プログラムパス
sl->SetDescription(NULL); // 説明(= ツールチップス)
sl->SetArguments(NULL); // コマンドライン引数
sl->SetWorkingDirectory(NULL); // 作業ディレクトリ
sl->SetIconLocation(NULL, 0); // Iconのパスまたはインデックス
sl->SetShowCmd(SW_SHOWNORMAL); // 起動時のウィンドウ表示
pf->Save(linkPath, TRUE); // ショートカットを保存
pf->Release(); // IPersistFileへのポインタを破棄
pf = NULL;
}
sl->Release(); // IShellLinkへのポインタを破棄
sl = NULL;
}
CoUninitialize(); // COMライブラリをクローズ
// ショートカットを移動
if (MoveFileW(linkPath, actualLinkPath) == 0)
{
int code = GetLastError();
cout << "MoveFileW() failed code = " << code << endl;
return 1;
}
return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: ショートカットの作成
ちゃんとMSDNに当たりましょう。
MSDNには,シェルリンクを作成するためのコードがちゃんと記述されています。
references)
最後のページに書かれているコードの,lpszPathLinkの引数型をLPCWSTRにし,MultiByteToWideCharで変換する部分を削り,main関数を追加して実行しましたが,普通にCSIDL_DESKTOP (CSIDL_DESKTOPDIRECTORY) や CSIDL_STARTMENU 以外にも作成できました。
というか,SHGetSpecialFolderLocation でわざわざデスクトップのIDListを取得して,そのIDListのディレクトリ名を取得し,そこへショートカットファイルの名前を追加しているプログラムですから,デスクトップに作成されるのは当然です。
# ちなみに,SHGetSpecialFolderPathでIDList経由せずにCSIDLから直接パスを取得できます。
任意フォルダのIDListはSHSimpleIDListFromPathで取得できますが,CSIDL使う関数群やSHSimpleIDListFromPathはDeprecatedなので,使う必要性がなければ使わないことが望ましいです。
SHGetFolderLocation等はSHGetKnownFolderIDList等で代替できますし。
MSDNには,シェルリンクを作成するためのコードがちゃんと記述されています。
オフトピック
lpszPathLinkの型がLPCWSTRではなくLPCSTRである点など,関数仕様に疑義はありますが
というか,SHGetSpecialFolderLocation でわざわざデスクトップのIDListを取得して,そのIDListのディレクトリ名を取得し,そこへショートカットファイルの名前を追加しているプログラムですから,デスクトップに作成されるのは当然です。
# ちなみに,SHGetSpecialFolderPathでIDList経由せずにCSIDLから直接パスを取得できます。
任意フォルダのIDListはSHSimpleIDListFromPathで取得できますが,CSIDL使う関数群やSHSimpleIDListFromPathはDeprecatedなので,使う必要性がなければ使わないことが望ましいです。
SHGetFolderLocation等はSHGetKnownFolderIDList等で代替できますし。