Re: [問題] VC2005 ShellExecute();
看板C_and_CPP (C/C++)作者zlw (www.eJob.gov.tw)時間16年前 (2009/06/17 12:45)推噓0(0推 0噓 1→)留言1則, 1人參與討論串2/3 (看更多)
看了你後來講的,追蹤一下大概知道你的意思了。
你用VC新增專案,選了很新奇的 Visual C++ -> CLR (Common Language Runtime) ->
Windows Form 應用程式。也就是要寫 C++/CLI 的程式。
然後你以前有寫 console 介面的程式跑一些處理後,會輸出一個文字檔 readme.txt。
你新增完專案後,想要試看看能不能用函數去開啟 readme.txt。
於是你找到兩個 Windows API 函數:ShellExecute 跟 WinExec
其實你可以用 <stdlib.h> 裡簡單的 system("notepad C:\xxx.txt");
根據msdn,WinExec 是為了跟 16位元 Windows 相容才提供,建議使用 CreateProcess()
而 ShellExecute() 則比較有趣,以 txt 來說,你用我的電腦->工具->資料夾選項->
檔案類型->txt->進階後,可以設定,當你在檔案總管點選txt按右鍵時的行為。
比如 .txt 你可以新增一個「用madedit開啟」或簡單點新增「edit」,然後對應執行此
動作的應用程式 D:\madedit.exe。當然 edit 會被翻譯成編輯。
以後你在txt檔,按右鍵選編輯,就會用 madedit 開啟該文字檔。
同理,ShellExecute()就是把 "open" 改成 "edit" 再選擇一個 txt 檔的路徑即可。
linux 桌面 GNOME 在 終端機 下有個指令,好像是 gnome-open 123.avi 就是做同樣
的事,跑這個指令後,就會等於你在 gnome 桌面環境點兩下 123.avi 去開啟他。
--
根據 msdn 的敘述,使用 ShellExecute() 你需要
Header shellapi.h
Import library shell32.lib
上面這是最低需求,我的習慣是明知道要呼叫的是 Windows API ,那就先
#include <windows.h> 再按下 F7 先編譯一次。
然後打函數名稱,不要打完就用 alt + → 叫出自動完成。
如果叫得出名字,代表你已經 include 原型宣告成功,不用再加 shellapi.h
windows.h 已經包含該檔。亦可看出此函數是否是巨集。Windows API 很多都是
有分 ANSI 跟 UNICODE 兩種版本,也就是根據專案設定是否支援 UNICODE 來
決定要呼叫 ShellExecuteA() 或 ShellExecuteW() 目前新版的 VC 預設值都是
UNICODE 支援開啟,所以你的字串常數一律都要改成 wchar_t 資料型態。
但可使用包含於 windows.h 裡的巨集 TEXT("open") ,這樣就能根據情況轉成
char 或 wchar_t。
故你應該寫 ShellExecute ( NULL, TEXT("open"), TEXT("C:\\sample.txt"), NULL,
NULL,SW_SHOWNORMAL );
然後你編譯,發生 lnk 2028 錯誤,但沒有編譯錯誤。這代表所有程式碼基本上語法正確
可通過編譯器,但連結時會錯誤。
很容易判斷出是 ShellExecute 的連結沒有成功,你要更改專案設定裡關於連結器
的選項,加入 shell32.lib 的連結設定。
或者不要更改專案設定,而是在 ShellExecute 所在的 cpp 檔假設是 main.cpp 裡,
加入編譯器前置處理指令 #pragma comment(lib, "shell32")
pragmatic info: 編譯器在 main.obj 加入註解,告知連結器增加連結 shell32 的參數
不用打全名 shell32.lib,連結器會到預設目錄去搜尋此靜態連結程式庫檔案。
※ 引述《lytn》之銘言:
: 不過我發現,要是當初專案用 主控台程式建立 ,就不會有ERROR,
: DEV C++ 也可以空專案直接跑,
: 所以......還是卡關了.
: 作者: lytn (sapphira) 看板: C_and_CPP
: 標題: [問題] VC2005 ShellExecute();
: 時間: Tue Jun 16 17:29:35 2009
: 我用 學校授權的 VS2005 ,應該是 .NET 架構吧
: 專案用 Windows From 開啟的
: 網路上找很多範例 例如 MSDN
: http://msdn.microsoft.com/en-us/library/bb762153(VS.85).aspx
: 雖然是看不太懂,不過我照著寫,或是網路上範例碼直接COPY用
: #include<windows.h>
: #include<shellapi.h>
: ShellExecute ( NULL, "open", "C:\\path\\to\\readme.txt", NULL, NULL,
: SW_SHOWNORMAL );
: 編譯時都會
: Error C2644:'ShellExecuteW':無法將參數2 從 'const char[5]' 轉換成 'LPCWSTR'
: 這要怎麼搞阿?
: ----原程式碼
: #include "stdafx.h"
: #include <windows.h>
: #include <shellapi.h>
: #include<vector>
: #include "Form1.h"
: #include "GloVar.h"
: #include "CivilClass.h"
: #include "BasicExcel.hpp"
: using namespace YExcel;
: using namespace VC_Project;
: [STAThreadAttribute]
: int main(array<System::String ^> ^args)
: {
: // HWND hwnd;
: // LPCWSTR filpat="open";
: WinExec("Notepad.exe", SW_SHOW); //這個會跑
: ShellExecute ( NULL, "open", "C:\\path\\to\\readme.txt", NULL, NULL,
: SW_SHOWNORMAL ); //這會錯
: Application::EnableVisualStyles();
: Application::SetCompatibleTextRenderingDefault(false);
: // 建立主視窗並執行
: Application::Run(gcnew Form1());
: return 0;
: }
: 另外想順便問, WinExec 跟 ShellExecute 有什麼差別?
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 124.8.131.252
推
06/17 13:36, , 1F
06/17 13:36, 1F
→
06/17 13:37, , 2F
06/17 13:37, 2F
推
06/17 13:39, , 3F
06/17 13:39, 3F
推
06/17 13:39, , 4F
06/17 13:39, 4F
整理
Visual C++ 相對於 GNU 的 gcc 或 g++,命令列指令用的是 cl.exe,提供完整編譯
C, C++, C++/CLI 成目的檔 .obj 的編譯器功能,再加上連結成 .exe 的功能。
在 Visual C++ 選工具 -> VS 200X Command Prompt 叫出命令提示字元後
打 cl src.cpp /c 就會只做編譯器的功能輸出 src.obj。
而不加 /c 則會輸出 src.obj 跟 src.exe。
若指令 cl 加上參數 /MT,則編譯選項為 multithread support & static link
/MD 同上但 dynamic link,故/MD輸出的執行檔較小,但缺所需dll的電腦就不能跑。
/MTd 與 /MDd 為等於在 debug 模式編譯出結果,會附加偵錯資訊。
而執行 link src.obj 可連結出 src.exe 但似乎無法做 /MT /MD 的指定,比較不方便。
--
obj 檔是 COFF (Common Object File Format) 格式,可用 VC 附的指令 dumpbin 解讀
或上網抓把 dumpbin 包裝成 GUI 的 wumpbin 軟體。
dumpbin 查詢 src.obj 可發現加入 #pragma comment (lib,"shell32") 後
在 .drectve section 裡有個 Linker Directive 多出一行 /DEFAULTLIB:"shell32"。
因此不管用 cl.exe 或 link.exe 都會記得在連結 src.obj 時,順便加上 shell32.lib
一起連結成 exe。
--
obj 檔做 dumpbin:
.bss section 用來放沒有初始化的變數,如以下的 count
#include <stdio.h>
int count; //就算加了 static 使其變成內部連結,還是在.bss區
int data = 2;
int main(){
int i;
int j = 2;
return 0;
}
※ http://blog.linux.org.tw/~jserv/archives/002030.html
.data 放資料,通常是有初始化的全域變數,比如上面的 int data = 2;
你在 .data 區就會看到四個16進位的Byte寫 02 00 00 00
(因為CPU是little endian,所以不是 00 00 00 02)
就算是變成 static int data = 2; 其差別也只是變成內部連結,其他都一樣。
而上面的 i 跟 j 是當程式執行到函數 main 時才隨便從屬於堆疊的那塊記憶體
區域,找 4 個 Byte 決定當成 i 或 j,一旦此函數結束,函數裡的
auto 變數所佔的區域可能就變成另外一個 auto (local) 變數拿去用。
.rdata 放唯讀資料,比如 "C:\\123.txt" 這樣的字串常數。在程式執行後
如果寫入這個區域所在的記憶體,則 Linux 上應該會回報 Segment fault,
Windows 好像是跳出 Runtime error 視窗。
.text 除了資料以外的東西,應該就是指令。
symbol table 每個 obj 都有一份,有好幾筆,某筆可能寫
00000000 SECT3 External ?count@@3HA (int count)
告訴我們當初那個未初始化的全域變數 int count; 被放在 Section 3
此例也就是 .bss section,放在裡面偏移位置 00000000 的地方,
其實就是第一個 Byte 所在。
它是 external (外部連結)。因為它的宣告沒有加 static,
所以其他的 obj 檔只要透過 extern int count; 就能呼叫他。
而也因為是外部連結,所以 C++ 編譯器對 count 的符號名稱裝飾的
比較用心,變成比較複雜的 ?count@@3HA
如果當初是宣告成 static (內部連結),其他 obj 無法呼叫的話,
名稱就只會簡單的改成 _count 而已。
--
exe 檔是 PE 格式 (Portable Executable),Windows 32/64 位元用的可執行檔格式
Linux 是 ELF,DOS有個有名的com,寫組語的話會發現它很平易近人,只要用組合語言
寫完,把程式起始位址假定為 0x100 然後組譯,改成 .com 就已經是合格的執行檔。
沒有relocation顧慮也沒有header,因為點兩下 OS 就把它載入到 0x100 記憶體去,
就好像在寫 boot loader 可以直接假定BIOS會把你寫的程式載入到 0000:7c00 一樣。
exe 應該是改良自 COFF,總之用 dumpbin 就可以解讀。
打開exe後發現多出一個 Imports,裡面會寫這個執行檔需要配合哪個dll,而且
是用到這個dll的哪個函數。也可以用功能更強的 Dependcy Walker 來看。
通常都是程式寫完要拿到別台電腦執行,結果被VC專案設定預設的選項 /MD 錶了
不能跑後才想到要來看 Imports 了什麼 dll。
而那這 ShellExecute() 其實用 /MD 或 /MT 都一樣到最後還是要用到 SHELL32.dll,
而且編譯的時候一定要用到 lib,我猜 lib 裡面是定義用來呼叫dll的程式碼,不確定。
直接在 runtime 呼叫 dll 取得其函數所在,就可以躲過 Dependency Walker 等的偵測
當然 dll 還是必須存在才能執行其功能的。如下:
#include <windows.h>
//略
HINSTANCE hPDLL;
hPDLL = LoadLibrary(TEXT("shell32.dll"));
//呼叫 Windows API,故指定函數「呼叫慣例」為 __stdcall
typedef HINSTANCE (__stdcall *ptr)(HWND, LPCSTR, LPCSTR, LPCSTR, LPCSTR, INT);
ptr ptrFun;
ptrFun = (ptr)GetProcAddress(hPDLL, "ShellExecuteA");
ptrFun(0, "edit", "C:\\windows\\winnt.bmp", 0, 0, SW_SHOWMAXIMIZED);
※ 編輯: zlw 來自: 124.8.131.252 (06/17 17:54)
→
06/17 18:06, , 5F
06/17 18:06, 5F
討論串 (同標題文章)
完整討論串 (本文為第 2 之 3 篇):
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章