廣告廣告
  加入我的最愛 設為首頁 風格修改
首頁 首尾
 手機版   訂閱   地圖  簡體 
您是第 6005 個閱讀者
 
發表文章 發表投票 回覆文章
  可列印版   加為IE收藏   收藏主題   上一主題 | 下一主題   
sob790717
數位造型
個人文章 個人相簿 個人日記 個人地圖
小人物
級別: 小人物 該用戶目前不上站
推文 x17 鮮花 x27
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片
推文 x0
[Basic][求助] ShellExecute API問題
ShellExecute API 程式碼在VB6之下這樣寫是沒問題的

模組
Public Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long


表單的一個按鈕加入程式碼
ShellExecute Me.hwnd, &q ..

訪客只能看到部份內容,免費 加入會員 或由臉書 Google 可以看到全部內容



[ 此文章被sob790717在2013-11-26 20:50重新編輯 ]


獻花 x0 回到頂端 [樓 主] From:臺灣中華電信股份有限公司 | Posted:2013-11-26 20:45 |
ebolaman 手機 會員卡
個人文章 個人相簿 個人日記 個人地圖
特殊貢獻獎

級別: 副版主 該用戶目前不上站
版區: 程式設計
推文 x38 鮮花 x458
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

VB6 的 Me.hwnd 在 .NET 等同 Me.Handle

不過這個值如果和視窗沒有關係,可以設為 0 (NULL)



.NET 比較習慣的 API 宣告用法是 DllImport 而且注意指標通常都是用 IntPtr (ㄧ種指標型態)

.NET style API 宣告:

複製程式
    <DllImport("shell32.dll")> _
    Private Shared Function ShellExecute(
            ByVal hwnd As IntPtr,
            ByVal lpOperation As String,
            ByVal lpFile As String,
            ByVal lpParameters As String,
            ByVal lpDirectory As String,
            ByVal nShowCmd As ShowCommands) As IntPtr
    End Function

呼叫:

複製程式
        ShellExecute(IntPtr.Zero,
                     "open",
                     "http://bbs.mychat.to/thread.php?fid=168",
                     "",
                     "",
                     ShowCommands.SW_SHOWNORMAL)

另外除了用 ShellExecute, 也可以用 .NET 內建的 Process.Start 達成同樣效果

我會比較建議用 Process.Start 因為程式碼更簡短,也不用 API:

複製程式
Process.Start("http://bbs.mychat.to/thread.php?fid=168")

有關 ShellExecute 各個參數的含意,以及範例,請參考

PInvoke: http://www.pinvoke.net/default.as...llExecute.html

MSDN: http://msdn.microsoft.com/en-us/li...esktop/bb762153(v=vs.85).aspx


本帖包含附件
zip Form1-code.rar   (2022-06-09 14:21 / 2 KB)   下載次數:2


My BOINC stats :

獻花 x1 回到頂端 [1 樓] From:台灣寬頻通訊顧問股份有限公司 | Posted:2013-11-26 23:45 |
sob790717
數位造型
個人文章 個人相簿 個人日記 個人地圖
小人物
級別: 小人物 該用戶目前不上站
推文 x17 鮮花 x27
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

下面是引用 ebolaman 於 2013-11-26 23:45 發表的 : 到引言文
VB6 的 Me.hwnd 在 .NET 等同 Me.Handle
不過這個值如果和視窗沒有關係,可以設為 0 (NULL)

.NET 比較習慣的 API 宣告用法是 DllImport 而且注意指標通常都是用 IntPtr (ㄧ種指標型態)
.NET style API 宣告:
.......

感謝您的解答
我會選擇使用ShellExecute是因為外部程式他自己存取檔案上的問題
那個程式他會參照開始位置來存取檔案
process.start好像沒辦法順邊幫他指定開始位置

所謂的開始位置是指


因為有些外部程式在執行時會參照他的開始位置來存取他的一些附屬檔案

例如" 111\A.exe" ShellExecute "222\B.exe" 之後
B.exe 會寫入一些檔案到跟他同級目錄(222)之下

但是如果換成Shell (或是VB2010的processor.start)指令
就會變成B.exe 會往A.exe的所在目錄(111)寫入一些原本應該在(222)目錄之下的檔案
變成B.exe會發生找不到檔案的問題,因為外部程序將檔案存錯資料夾了
所以不得不用此API

或是我聽其他高手可以先將processor.start切換工作路徑再執行外部程式
但是因為沒經驗所以不太明白


獻花 x0 回到頂端 [2 樓] From:臺灣中華電信股份有限公司 | Posted:2013-11-27 14:26 |
ebolaman 手機 會員卡
個人文章 個人相簿 個人日記 個人地圖
特殊貢獻獎

級別: 副版主 該用戶目前不上站
版區: 程式設計
推文 x38 鮮花 x458
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

下面是引用 sob790717 於 2013-11-27 14:26 發表的 : 到引言文


感謝您的解答
我會選擇使用ShellExecute是因為外部程式他自己存取檔案上的問題
那個程式他會參照開始位置來存取檔案
process.start好像沒辦法順邊幫他指定開始位置

所謂的開始位置是指


因為有些外部程式在執行時會參照他的開始位置來存取他的一些附屬檔案

例如" 111\A.exe" ShellExecute "222\B.exe" 之後
B.exe 會寫入一些檔案到跟他同級目錄(222)之下

但是如果換成Shell (或是VB2010的processor.start)指令
就會變成B.exe 會往A.exe的所在目錄(111)寫入一些原本應該在(222)目錄之下的檔案
變成B.exe會發生找不到檔案的問題,因為外部程序將檔案存錯資料夾了
所以不得不用此API

或是我聽其他高手可以先將processor.start切換工作路徑再執行外部程式
但是因為沒經驗所以不太明白

Process.Start() 也可以指定開始位置哦



Process.Start(...) 有許多呼叫方式,可以參考 MSDN 的這個方式

http://msdn.microsoft.com/...ry/0w4h05yb

Process.Start(psi)

psi 是一個 ProcessStartInfo 實例

除了你說的 開始位置 (Working Directory),還可以指定參數等

用法如下

複製程式
        Dim psi As New ProcessStartInfo


        With psi
            .FileName = "將被執行的檔案"
            .WorkingDirectory = "開始位置"
        End With


        Process.Start(psi)

範例:

複製程式
Public Class Form1
    Private Sub Button1_Click() Handles Button1.Click
        Dim psi As New ProcessStartInfo


        With psi
            .FileName = Application.ExecutablePath
            .WorkingDirectory = IO.Path.GetTempPath()
        End With


        Process.Start(psi)
    End Sub


    Private Sub Form1_Load() Handles MyBase.Load
        MessageBox.Show(String.Format("Working directory: {0}",
                                      IO.Directory.GetCurrentDirectory()))
    End Sub


End Class

Application.ExecutablePath 是自己 .exe 的完整路徑

IO.Path.GetTempPath() 是 Temp 暫存資料夾

以上程式呼叫自己,當表單載入時,用訊息顯示目前程式的開始位置



本帖包含附件
zip Form1-code.rar   (2022-06-09 14:21 / 2 KB)   下載次數:1


My BOINC stats :

獻花 x1 回到頂端 [3 樓] From:台灣寬頻通訊顧問股份有限公司 | Posted:2013-11-27 23:45 |
sob790717
數位造型
個人文章 個人相簿 個人日記 個人地圖
小人物
級別: 小人物 該用戶目前不上站
推文 x17 鮮花 x27
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

只剩最後一個小小的問題

複製程式
        Dim TWN_GameClientStartInfo As New ProcessStartInfo


        With TWN_GameClientStartInfo
            .FileName = My.Settings.TWN_TR_GameClient_Path  '"將被執行的檔案"
            Dim TWN_PathWithoutFileName As String
            TWN_PathWithoutFileName = My.Settings.TWN_TR_GameClient_Path
            TWN_PathWithoutFileName = Replace(TWN_PathWithoutFileName, "\talesrunner.exe", "")
            .WorkingDirectory = TWN_PathWithoutFileName  '"開始位置"

        End With

        MsgBox("dir  " & TWN_GameClientStartInfo.WorkingDirectory & vbCrLf & "file   " & TWN_GameClientStartInfo.FileName)


因為我自己的程式設計方法而遇到了一點 .WorkingDirectory 上的小問題
以上程式碼我另外加入一行 Dim TWN_PathWithoutFileName As String 定義字串
然後把設定組態的一個字串讀入到TWN_PathWithoutFileName
再使用Replace函式去除掉檔案名之後再放入到.WorkingDirectory

請問以上作法是否有更簡略化的寫法呢?
還是已經是最好的了?


獻花 x0 回到頂端 [4 樓] From:臺灣中華電信股份有限公司 | Posted:2013-11-28 20:26 |
ebolaman 手機 會員卡
個人文章 個人相簿 個人日記 個人地圖
特殊貢獻獎

級別: 副版主 該用戶目前不上站
版區: 程式設計
推文 x38 鮮花 x458
分享: 轉寄此文章 Facebook Plurk Twitter 複製連結到剪貼簿 轉換為繁體 轉換為簡體 載入圖片

有關路徑的處理,交給 .NET 內建的 IO.Path 底下的函式就對了

IO.Path.GetDirectoryName("C:\MyDir\MySubDir\myfile.ext") -> "C:\MyDir\MySubDir"

MSDN: http://msdn.microsoft.com/en-us/library/...directoryname.aspx

所以部分程式碼可改成

複製程式
TWN_PathWithoutFileName = My.Settings.TWN_TR_GameClient_Path
.WorkingDirectory = IO.Path.GetDirectoryName(TWN_PathWithoutFileName)

其他小建議:

1. 小函式內 變數不宜太長,否則打字容易錯,解讀也容易錯 -> 在宣告變數前用註解,這個變數是做什麼的

2. 如果是一個實例 (例 Dim a As New ProcessStartInfo 那麼 a 就是實例)
開頭最好是小寫,避免和大寫開頭的 Class 搞混 (ProcessStartInfo 就是一個 Class)

3. 可以開頭用 Dim file As String = My.Settings.TWN_TR_GameClient_Path 
後面程式碼都用 file 來寫,未來如需修改,只需修改一處即可

4. 如需用 MsgBox 顯示訊息,如果出現太長的連接 (例: "A" & var1 & "B" & var2 & "C")
可以考慮用 String.Format("A {0} B {1} C", var1, var2) 來達成,使程式碼更有彈性


My BOINC stats :

獻花 x1 回到頂端 [5 樓] From:台灣寬頻通訊顧問股份有限公司 | Posted:2013-11-28 21:56 |

首頁  發表文章 發表投票 回覆文章
Powered by PHPWind v1.3.6
Copyright © 2003-04 PHPWind
Processed in 0.117674 second(s),query:16 Gzip disabled
本站由 瀛睿律師事務所 擔任常年法律顧問 | 免責聲明 | 本網站已依台灣網站內容分級規定處理 | 連絡我們 | 訪客留言