广告广告
  加入我的最爱 设为首页 风格修改
首页 首尾
 手机版   订阅   地图  繁体 
您是第 6011 个阅读者
 
发表文章 发表投票 回覆文章
  可列印版   加为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.070905 second(s),query:16 Gzip disabled
本站由 瀛睿律师事务所 担任常年法律顾问 | 免责声明 | 本网站已依台湾网站内容分级规定处理 | 连络我们 | 访客留言