<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Architecting Life &#187; ShellExecute</title>
	<atom:link href="http://xujiwei.com/blog/tags/shellexecute/feed/" rel="self" type="application/rss+xml" />
	<link>http://xujiwei.com/blog</link>
	<description>Just do it</description>
	<lastBuildDate>Thu, 05 Apr 2012 17:19:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>REALbasic 中使用 ShellExecute 执行命令</title>
		<link>http://xujiwei.com/blog/using-shellexecute-in-realbasic/</link>
		<comments>http://xujiwei.com/blog/using-shellexecute-in-realbasic/#comments</comments>
		<pubDate>Fri, 16 Oct 2009 13:50:40 +0000</pubDate>
		<dc:creator>Xu Jiwei</dc:creator>
				<category><![CDATA[Desktop]]></category>
		<category><![CDATA[REALbasic]]></category>
		<category><![CDATA[ShellExecute]]></category>
		<category><![CDATA[Win32]]></category>

		<guid isPermaLink="false">http://tmp.xujiwei.com/blog/?p=72</guid>
		<description><![CDATA[<a href="http://xujiwei.com/blog/using-shellexecute-in-realbasic/" title="REALbasic 中使用 ShellExecute 执行命令"></a>在 REALbasic 中，如果需要执行 cmd 命令，可以直接使用 Shell 类，但是这样的话，编译成 Windows 程序时会额外需要一个 Shell.dll 的动态链接库，这对于我这样的 1exe 爱好者是不能忍受的。但是对于 Mac OS X 和 Linux 的生成目标来说，是不存在这个问题的，因为 Mac OS X 的应用程序本身就是一个文件夹，而 Linux 的目标不会生成额外的链接库。因此，需要针对 Windows 进行特殊处理。于是在网上搜索解决方案，找到了 VB 中执行程序的几种方法： 1. 使用 CreateProcess 通过 CreateProcess 以及使用管道，可以执行外部程序并获取输出，但是这个方法过于烦琐，并且我也不需要外部进程执行完毕后的输出结果，因此不采用。 2. 使用 Shell 方法 VB 里有一个 Shell 方法，但是在 RB 中并没有，所以此路不通。 3. 使用 ShellExecute 这个方法同样是一个系统 API，可以直接通过 RB 的 declare 声明并调用它，在测试之后，使用 declare 来使用系统 API 不会生成额外的 dll，正是我需要的。 首先在 RB 的某个模块中添加一个方法 ShellExecute，用来封装对系统 API 的请求： function ShellExecute(hWnd as Integer, lpOperation as String, _ lpFile as String, lpParameters as String, lpDirectory as String, nShowCmd as Integer) 注意，在 RB 中添加方法时，参数列表中的 _ 需要去掉，这里是为了排版的需要而加上的。 这个 API 是定义在 shell32.dll 中的，在 ShellExecute 方法中先需要声明： soft declare function ShellExecuteA Lib &#8221;shell32.dll&#8221; _ (ByVal hWnd As Integer, ByVal lpOperation As CString, _ ByVal lpFile As CString, ByVal lpParameters As CString, _ ByVal lpDirectory As CString, ByVal nShowCmd As Integer) As Integer soft declare function ShellExecuteW Lib &#8221;shell32.dll&#8221; _ (ByVal hWnd As Integer, ByVal lpOperation As CString, _ ByVal lpFile As CString, ByVal lpParameters As CString, _ ByVal lpDirectory As CString, ByVal nShowCmd As Integer) As Integer 然后来调用这个 API： dim ret as Integer Try ret = ShellExecuteW(hWnd, ConvertEncoding(lpOperation, Encodings.UTF16), _ ConvertEncoding(lpFile, Encodings.UTF16), _ ConvertEncoding(lpParameters, Encodings.UTF16), _ ConvertEncoding(lpDirectory, &#8230;<p class="read-more"><a href="http://xujiwei.com/blog/using-shellexecute-in-realbasic/">Read more &#187;</a>]]></description>
			<content:encoded><![CDATA[<a href="http://xujiwei.com/blog/using-shellexecute-in-realbasic/" title="REALbasic 中使用 ShellExecute 执行命令"></a><p>在 REALbasic 中，如果需要执行 cmd 命令，可以直接使用 Shell 类，但是这样的话，编译成 Windows 程序时会额外需要一个 Shell.dll 的动态链接库，这对于我这样的 1exe 爱好者是不能忍受的。但是对于 Mac OS X 和 Linux 的生成目标来说，是不存在这个问题的，因为 Mac OS X 的应用程序本身就是一个文件夹，而 Linux 的目标不会生成额外的链接库。因此，需要针对 Windows 进行特殊处理。于是在网上搜索解决方案，找到了 VB 中执行程序的几种方法：</p>

<p><strong>1. 使用 CreateProcess</strong></p>

<p>通过 CreateProcess 以及使用管道，可以执行外部程序并获取输出，但是这个方法过于烦琐，并且我也不需要外部进程执行完毕后的输出结果，因此不采用。</p>

<p><strong>2. 使用 Shell 方法</strong></p>

<p>VB 里有一个 Shell 方法，但是在 RB 中并没有，所以此路不通。</p>

<p><strong>3. 使用 ShellExecute</strong></p>

<p>这个方法同样是一个系统 API，可以直接通过 RB 的 declare 声明并调用它，在测试之后，使用 declare 来使用系统 API 不会生成额外的 dll，正是我需要的。</p>

<p>首先在 RB 的某个模块中添加一个方法 ShellExecute，用来封装对系统 API 的请求：</p>

<blockquote>function ShellExecute(hWnd as Integer, lpOperation as String, _
lpFile as String, lpParameters as String, lpDirectory as String, nShowCmd as Integer)</blockquote>

<p>注意，在 RB 中添加方法时，参数列表中的 _ 需要去掉，这里是为了排版的需要而加上的。</p>

<p>这个 API 是定义在 shell32.dll 中的，在 ShellExecute 方法中先需要声明：</p>

<blockquote>soft declare function ShellExecuteA Lib &#8221;shell32.dll&#8221; _
(ByVal hWnd As Integer, ByVal lpOperation As CString, _
ByVal lpFile As CString, ByVal lpParameters As CString, _
ByVal lpDirectory As CString, ByVal nShowCmd As Integer) As Integer

soft declare function ShellExecuteW Lib &#8221;shell32.dll&#8221; _
(ByVal hWnd As Integer, ByVal lpOperation As CString, _
ByVal lpFile As CString, ByVal lpParameters As CString, _
ByVal lpDirectory As CString, ByVal nShowCmd As Integer) As Integer</blockquote>

<p>然后来调用这个 API：</p>


<div class="wp_syntax"><div class="code"><pre class="vb" style="font-family:monospace;">  <span style="color: #151B8D; font-weight: bold;">dim</span> ret <span style="color: #151B8D; font-weight: bold;">as</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>
    Try
      ret = ShellExecuteW(hWnd, ConvertEncoding(lpOperation, Encodings.UTF16), _
      ConvertEncoding(lpFile, Encodings.UTF16), _
      ConvertEncoding(lpParameters, Encodings.UTF16), _
      ConvertEncoding(lpDirectory, Encodings.UTF16), nShowCmd)
    Catch
      ret = ShellExecuteA(hWnd, lpOperation, lpFile, lpParameters, lpDirectory, nShowCmd)
    <span style="color: #8D38C9; font-weight: bold;">End</span>
    return ret</pre></div></div>


<p>把 ShellExecuteW 放在 Try &#8230; Catch 中是为了兼容的需要，因为像 Windows 98 这样比较老的系统中，系统内部编码还不是 Unicode，还没有 ShellExecuteW 这样结尾是 W 的 API。</p>

<p>另外，因为 RB 内部是使用的 UTF-8 编码，而系统 API ShellExecuteW 使用的编码是 Unicode，所以参数在传递前需要进行转码，将字符串参数值转换为 Unicode 编码，否则在执行一个明明正确的命令时，会出现“找不到文件”的错误。</p>

<p>好了，这样就可以使用 ShellExecute 方法来执行外部程序了，例如：</p>


<div class="wp_syntax"><div class="code"><pre class="vb" style="font-family:monospace;">  #if TargetWin32
    <span style="color: #151B8D; font-weight: bold;">dim</span> ret <span style="color: #151B8D; font-weight: bold;">as</span> <span style="color: #F660AB; font-weight: bold;">Integer</span>
    ret = Win32Helper.ShellExecute(hWnd, <span style="color: #800000;">&quot;open&quot;</span>, <span style="color: #800000;">&quot;cmd.exe&quot;</span>, _
    <span style="color: #800000;">&quot;/c shutdown -t 10&quot;</span>, <span style="color: #800000;">&quot;&quot;</span>, 0)
  #endif</pre></div></div>


<p>上面的代码就调用 cmd.exe 执行了命令 shutdown -s -t 10，也就是 10 秒后关机。</p>

<p>其实这个方法也可以用来打开文档或者网址，具体的用法可以去 MSDN 找一找。</p>

<p>当然，如果不在乎生成的 Windows 目标还有额外的 dll 的话，完全可以使用 RB 自带的 Shell 类，功能也强上不少。</p>
]]></content:encoded>
			<wfw:commentRss>http://xujiwei.com/blog/using-shellexecute-in-realbasic/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

