• 締切済み

ショートカットからフルパスを取得する方法について

こちら【http://www.kab-studio.biz/Programing/Codian/ShellExtension/09.html】のサイトを参考にしてショートカットからアプリ実行ファイルのフルパスを取得しようとしています。開発環境はMicrosoft Visual Studio 2010です。 以下のソースで特にエラーなく実行はできるのですが、アプリによっては取得できないものがあります。 デスクトップにあるショートカットアイコンですべて動作テストを行っています。 Janetter.lnk、Microsoft Visual Studio 2010.lnk、MetasequoiaLER3.0.lnk、Microsoft Office Word 2007.lnk の四つを試しました。 JanetterとVisualStudioはフルパスが問題なく取得でき、アドレスをたどってアイコンをダブルクリックしてみるとアプリが起動できます。 Metasequoiaは全く取得できず、wordはC:\windows\Installer\{90120000-0011-0000-0000000FF1CE}}\wordicon.exeを取得しました。 アドレスをたどり、wordicon.exeをダブルクリックして起動しようとしてもwordを起動することはできませんでした。 アプリによって取得できるものとできないものの差は何なのでしょうか? どうすればすべての実行ファイルのフルパスを取得できるでしょうか、アドバイスを頂けると助かります。 #include <windows.h> #include <shlobj.h> #include <iostream> #include <string> IShellLink *pShellLink; //IShellLinkへのポインタ IPersistFile *pPersistFile; //IPersistFileへのポインタ bool getLnk(){ HRESULT hRes;//結果 //メンバの初期化 pShellLink = NULL; pPersistFile = NULL; //OLE【 Object Linking and Embedding 】アプリケーションソフト間でデータを転送・共有するための仕組み //OLEを使うために初期化 hRes = ::CoInitialize(NULL); //エラー対処 if(hRes == E_OUTOFMEMORY) return false; if(hRes == E_INVALIDARG) return false; if(hRes == E_UNEXPECTED) return false; // 空のインターフェイスを用意 // ファイル情報の格納場所の確保 hRes = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink,(LPVOID *)&pShellLink); //エラー対処 if(hRes == CLASS_E_NOAGGREGATION) return false; if(hRes == REGDB_E_CLASSNOTREG) return false; //IPersistFileへのポインタを取得 IShellLinkの操作に必要 hRes = pShellLink->QueryInterface(IID_IPersistFile,(LPVOID*)&pPersistFile); //エラー対処 if(hRes != S_OK) return false; return true; } bool UngetLnk(){ //IPersistFileへのポインタの破棄 if(pPersistFile != NULL) pPersistFile->Release(); //IShellLinkへのポインタの破棄 if(pShellLink != NULL) pShellLink->Release(); ::CoUninitialize(); return true; } bool LinkLoad(LPCTSTR lnkpass){ HRESULT hRes; // 結果 OLECHAR ochLinkFile[MAX_PATH]; //ユニコードに変換 ::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,lnkpass,-1,ochLinkFile,MAX_PATH); //ショートカットファイルの読み込み hRes = pPersistFile->Load(ochLinkFile,STGM_READ); if(hRes != S_OK) return false; //リンクの決定 ショートカットの読み込み hRes = pShellLink->Resolve(NULL,SLR_UPDATE); if(hRes != NOERROR) return false; return true; } int main(){ LPCTSTR lnkpath="C:\\Users\\Momo\\Desktop\\Microsoft Office Word 2007.lnk"; LPSTR fullpath; char x[100]; fullpath = x; if(getLnk()){ LinkLoad(lnkpath); pShellLink->GetPath(fullpath, _MAX_PATH, NULL, 0); UngetLnk(); std::cout << fullpath << std::endl; }else std::cout << "false" << std::endl; return 0; }

みんなの回答

回答No.1

回答がないようなので、字面だけ見た印象を。 ただし、非専門家で、MS Windows も C++ もほとんど、触れたことがありません。 - 関数 LinkLoad() の引数の lnkpass は lnkpath のミススペルか。 -- 別に、ミススペルでも、関数内で整合してるので、問題ないと思います。 - 関数 main() の fullpath は 100 じゃなく MAX_PATH の領域を確保しないとダメなのでは。 -- コンパイラが文句言わないなら、問題ないのかもしれません。 - main() 中のメソッド呼び出し GetPath() の _MAX_PATH は MAX_PATH のミススペルか。 -- こっちのミススペルはダメだと思います。 - 関数 UngetLnk() は getLnk() と対(つい)で、main() の else 側でも必要なのでは。 -- つまり、if 文の下に移動したほうが良いかと思います。

関連するQ&A

  • システムの特殊なフォルダのパス名の取得を取得しようとしています。

    システムの特殊なフォルダのパス名の取得を取得しようとしています。 VC++2008 Express EditionでSHGetSpecialFolderPathをつかって パスを取ってみようとネット上の例だから拝借して 下記のようなソースを書いてみたのですが、 出てくる結果が、どの場所のパスをとっても「C」しか出てこないのです。 これってなにが原因なのでしょうか? どなたかお教え願えないでしょうか? [ソース] #include<stdio.h> #include<shlobj.h> int main(){ TCHAR buf[_MAX_PATH]; SHGetSpecialFolderPath(NULL, buf, CSIDL_DESKTOPDIRECTORY, FALSE); printf("デスクトップのパスは %s です\n",buf); return 0x00; }

  • iniファイルのパス取得m_pszProfileNameについて

    InitInstanceで、m_pszProfileNameを変更していますが、 別の関数(InitTest)を用意し、そこでパス変更をしようと思っています。 追加関数のif (m_pszProfileName) {のところで、 不適切なptrとなってしまいます。 ifの中に入っていきません。 現行のソース BOOL CXXXApp::InitInstance() { if (m_pszProfileName) { free(m_pszProfileName); } m_pszProfileName = _tcsdup(iniPath); : : パスの変更に失敗した時 return FALSE; : return TRUE; } 追加関数 BOOL CXXXApp::InitTest() { if (m_pszProfileName) { ←ここがTRUEにならず、不適切なptr free(m_pszProfileName); } m_pszProfileName = _tcsdup(iniPath); : : パスの変更に失敗した時 return FALSE; : return TRUE; } 変更後は、オーバーライドしたInitInstanceでは、 何も処理を行わず、そのままTRUEをreturnさせます。 追加関数で、m_pszProfileNameが初期化できていないのでしょうか? どうすれば、追加関数で、iniファイルのパス変更ができるか教えてください。 iniファイルは、exeと同じフォルダに設置します。

  • リスト内の各ショートカットの参照先を一括取得したい

    windowsのエクスプローラーのショートカット(拡張子.lnk)のフルパスのリストがあります。 リスト内の各ショートカットの参照先を、コマンドプロンプトやパワーシェル等で一括で取得したいです。 方法をご存知の方、教えてください。 よろしくお願いします。

  • DLLの明示的な読み込みの方法

    開発環境:WindowsXP sp2 + VisualStudio2005 MSDNやその他のWebページで、DLLの明示的なロードについて勉強しています。 試しに以下のようなコードを書いてみたのですが、コンパイルは通りますが、実行時にDLLが読み込まれているのにもかかわらず、関数のアドレスが取得できません。 ---DLLのコード--- #include <iostream> using namespace std; __declspec(dllexport) void printMessage() { cout<<"printMessage関数が呼ばれた"<<endl; } ---終わり--- コンパイルしたDLLのみをDLLを使用した実行形式がコンパイル後に収納されるフォルダに移動して、以下のコードを書いてコンパイルしました。 ---EXEのコード--- #include <windows.h> #include <iostream> typedef void(*TFUNC)(); int main(void) { HINSTANCE hInstDLL; TFUNC DllFunction; //DLLの読み込み hInstDLL=LoadLibrary(L"dll.dll"); if(hInstDLL==NULL) { std::cout<<"ERROR"<<std::endl; return 0; } //printMessage関数のアドレスを取得 DllFunction=(TFUNC)GetProcAddress(hInstDLL,"printMessage"); //この辺りがおかしいかも知れない //関数の使用 if(DllFunction==NULL) { std::cout<<"ERROR"<<std::endl; FreeLibrary(hInstDLL); return 0; } DllFunction(); //DLLの解放 if(!FreeLibrary(hInstDLL)) return 0; return 0; } ---終わり--- DLLは見つかる物の、どうも上手くいかないようです......原因は何なのでしょうか。

  • プログラムの説明

    C++の初心者です。 ↓のプログラムの動作はさっぱりわかりませんが、それについての説明は具体的に教えていただきたいです。(できれば、詳しく) #include <iostream> #include <string> int getNinzu(int ARGC, char *ARGV[]) throw (char const *){ if(ARGC!=2){ throw "Needs only one argument."; } int ninzu=std::atoi(ARGV[1]); if(ninzu<=0){ throw "Value is too small."; } return ninzu; } #include <cstdlib> #include <ctime> int randfive(){ static bool firsttime=true; if(firsttime){ firsttime=false; std::srand(std::time(NULL)); } return static_cast<int>(static_cast<double>(std::rand())/RAND_MAX*(5+1)); } #include <iomanip> int main(int ARGC, char* ARGV[]){ std::string cmdname=ARGV[0]; int ninzu; try{ ninzu=getNinzu(ARGC,ARGV); std::cout << std::setfill('0'); for (int i = 1; i <= ninzu; ++i) { int score = 0; for (int k = 0; k < 20; ++k) score += randfive(); std::cout << "C" << std::setw(5) << i << " " << score << '\n'; } }catch(char const *str){ std::cerr << str << std::endl << "Usage: " << cmdname << " ninzu" << std::endl; return 1; } }

  • 戻り値の取得が出来ません

    いつもお世話になっています。 ファイルを抽出するプログラムを作成しています。 関数の中で検索処理を行い、ファイルパスを返そうとしたのですが、returnの直前までは値が入っているのに、関数の呼び出し先で値が取れなくなってしまいました。 当方JAVA経験はあるものの、ポインタなどもまだ把握し切れていないC初心者なので、 不勉強で申し訳ないですが、ちょっと急ぎの用事のため、質問させて下さい。 **呼び出し元** char* SearchPastFile(CString strFolder,int imageFlag,char transTime[15]); void main( void ){ char* prevFile; // 転送元ファイル名 prevFile = SearchPastFile(cTransPath,iImageFlag,transTime); // 過去ファイルの取得【現状NULL】 MessageBox(NULL,prevFile,"パス",MB_OK);【←(確認用)空の状態】 } **関数** char* SearchPastFile(CString strFolder, int imageFlag, char transTime[15]){ CFileFind FileFind; // すべてのファイルを検索します CString strSearchFile = strFolder + _T("\\*.*"); if(!FileFind.FindFile(strSearchFile)) { Log("ファイルが見つかりませんでした。"); return NULL; } char *p; // ファイルパス BOOL bContinue = TRUE; while(bContinue){ (検索処理中略) // 24時間前のファイル if(imageFlag==1 && spanDays==-1){ Log("ファイルが見つかりました。"); MessageBox(NULL,p,"パス",MB_OK);【←(確認用)ここではパスが取れている】 return p; // 48時間前のファイル } else if(imageFlag==2 && spanDays==-2){ Log("ファイルが見つかりました。"); return p; } } }; return NULL; } prevFileに値を入れたいです。 他の回答を見て、p = (char*)malloc( 16 );などもやってみましたが、取れませんでした。 思い当たる節などがあれば、御教授よろしくお願いします。

  • AfxLoadLibrary関数で、DLLのハンドルが取得できない

    はじめまして。 タイトルの通りですが、AfxLoadLibraryを使用して、DLLのハンドルを取得しようとしています。(取得したハンドルでGetProcAddress関数を使用する為) ここで、AfxLoadLibraryの戻り値となる、ハンドルがNULL(0x0000)となってしまい、GetProcAddressによる関数ポインタの設定が行えない状況となっています。 FormatMessage関数とGetLastErrorを使用し、原因を調べたところ、「指定されたモジュールが見つかりません」というメッセージとなりました。 AfxLoadLibraryで指定しているDLLについては、Exeファイルと同じフォルダ内に存在し、かつ、名前についても間違っていません。 試しに、別DLLを、上記NGとなるDLLと同様の名前で作成してみたところ、ハンドルの取得に成功したので、EXE側のコーディングミスという所は考えづらいところです。 お手数ですが、他の原因に心あたりがありましたらご教唆願います。 <コーディング(一部抜粋)> ---------------------------------------------------------------- HINSTANCE m_handle_Aaa; typedef WORD (WINAPI *LPOpenAaa)(); LPOpenAaa lpOpenAaa; BOOL DllLoad(void) { // Load Dll m_handle_Aaa = AfxLoadLibrary("AaaDLL.dll"); if(m_handle_Aaa < (HINSTANCE)HINSTANCE_ERROR) { PutLastError(); // Error Message return FALSE; } // Get Function Pointer lpOpenAaa = (LPOpenAaa)GetProcAddress( m_handle_Aaa, "OpenAaa"); if(lpOpenAaa == NULL) return FALSE; ・ ・ ・ ----------------------------------------------------------------

  • ウィンドウタイトルの取得方法

    WIN98 MFC vc++6.0 2重起動を防止し、既に起動している時は、ウィンドウを最上位にもってくる以下のコードにて ウィンドウのタイトルを設定しているIDS_WINDOWTITLEはどこで定義し、どうやってタイトルを設定すれば良いのでしょうか? BOOL CMyApp::InitInstance() { 略  // アプリケーションの二重起動防止  ::CreateMutex(NULL, TRUE, m_pszExeName);  if( GetLastError() == ERROR_ALREADY_EXISTS) {   // 既に起動されている場合は、CWnd::FindWindow関数を使って   // 起動されているアプリケーションのウィンドウを取得し、   // そのウィンドウを最上位へ持ってくる   CString str;   str.LoadString(IDS_WINDOWTITLE);   // IDS_WINDOWTITLEにはウィンドウのタイトルを設定している   CWnd* pWnd = CWnd::FindWindow(NULL, str);   if( pWnd )   pWnd->SetForegroundWindow();   return FALSE;  }

  • basic_ostreamクラスについて

    http://msdn.microsoft.com/ja-jp/library/k262esc6.aspx をみると、VC++2010のbasic_ostream::sentryには  operator bool( ) const; がある事になっていますが、実際は無いようです。 VC++2010 Express Edition のostream(C:\Program Files\Microsoft Visual Studio 10.0\VC\include\ostream)を見ると、sentryにoperator bool() constがありませんでした。 代わりに __CLR_OR_THIS_CALL _OPERATOR_BOOL() const { // test if stream state okay return (_Ok ? _CONVERTIBLE_TO_TRUE : 0); } というのがありますが、 #define _STD ::std:: #define _OPERATOR_BOOL operator _STD _Bool_type と定義されており、operator bool( ) constとは別物でした。 このため、basic_ostream::sentry::operator bool( )を使用しているソースをVC++2010(Express Edition)でビルドしようとするとエラーになります。 ちなみに、このソースをVC++2008 Express Editionでビルドすると通ります。 質問なのですが、 1)basic_ostream::sentry::operator bool( )を使うソースをVC++2010 Express Editionでビルドするにはどうすれば良いでしょうか? 2)なぜVC++2010 Express Editionからbasic_ostream::sentry::operator bool( )がなくなってしまったのでしょうか? ご存知の方、ご教授ください。 よろしくお願いします。

  • Win32でシリアル通信

    現在.NET2003のWin32を使ってシリアル通信を行うプログラムを作成中なんですが、CreateFile()、WriteFile()といった関数を使っているのですがどうもうまくいきません。 どなたかWin32について詳しい方、ご教授頂けないでしょうか?また、こういった事が書いているHP等をご存知の方教えて頂けないでしょうか? ちなみに、ポートを開く部分は下記のようになっているのですが、何か間違いがあれば教えて下さい。 お願い致します。 /* シリアルポートを開く */ BOOL SerialOpenPort(int nPortNumber) { char szSerial[256]; if(g_ahSerial[nPortNumber - 1] != NULL) { return FALSE; } sprintf(szSerial, "COM%d", nPortNumber); g_ahSerial[nPortNumber - 1] = CreateFile( szSerial, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );   if(g_ahSerial[nPortNumber - 1] == INVALID_HANDLE_VALUE) { g_ahSerial[nPortNumber - 1] = NULL; return FALSE; } if(!InitDCB(nPortNumber)) { return FALSE; }  if(!InitCommTimeOuts(nPortNumber)) { return FALSE; }  return TRUE; }

専門家に質問してみよう