開発環境はWindowsXP/7とDelphi6です。
今作っているプログラムでどうしてもDOSのコマンドラインから
実行しなければならないプロセスがあります。
普通にやるとけっこう大きなDOS窓が出て、不格好です。
DOS窓を出さない、画面外に出す、極めて目立たない
小さな状態で出すなど、なにか良い方法はないでしょうか?
>DOS窓を出さない、
現在はどのようなコードで,どのようなプログラムを実行しているのでしょうか ?
(1) 現在の方法を使用して,コマンドプロンプトを表示しないように修正する
(2) コマンドプロンプトが表示しないようにできるのであれば,他の方法でもよい
備考
WindowsXP/7 には DOS 窓というのはありません.
おそらくコマンドプロンプトのことだと思います.
>DOSのコマンドラインから実行しなければならないプロセスがあります。
>(改行位置を変更しました)
ということは,現在は,コマンドプロンプトを起動して,そこにコマンドを入力して
実行している,ということでしょうか ?
Mr.XRAYさん、さっそくのレスポンスありがとうございます。
具体的に起動したいのはuudx.exeです。
> 現在は,コマンドプロンプトを起動して,そこにコマンドを入力して
> 実行している,ということでしょうか ?
起動するコードは下記のようにしています。
procedure TForm1.Button1Click(Sender: TObject);
var
res : boolean;
Si : TStartupInfo;
Pi : TProcessInformation;
begin
GetStartupInfo(Si);
res := CreateProcess(nil,
PChar('uudx.exe'),
nil,
nil,
False,
CREATE_DEFAULT_ERROR_MODE,
nil,
nil,
SI,
PI);
if res = false then MessageDlg('ソフトの起動に失敗しました。',mtError,[mbOk],0);
end;
例えば、こんなコードはどうでしょうか?
Win7,D6では動作しました。
ただ、Win7,XE4ではエラーが出ました。
var
cmd: string;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
StartupInfo.cb := SizeOf(TStartupInfo);
//コマンドプロンプトウィンドウを非表示に
StartupInfo.dwFlags := StartF_UseShowWindow;
StartupInfo.wShowWindow := SW_Hide;
//DOSのTreeコマンドを実行
cmd := 'command.com /c tree c:\temp > c:\tree.txt';
if CreateProcess(nil,
PChar(cmd),
nil,
nil,
False,
0,
nil,
'c:\',
StartupInfo,
ProcessInfo) then begin
WaitForSingleObject(ProcessInfo.hProcess, Infinite);
CloseHandle(ProcessInfo.hProcess);
end;
end;
deldelさん、具体的なコードを提示していただいて
ありがとうござます。今日さっそく書き換えたところ、
想定していた通りの動作になりました。
これは今後も便利そうなので、汎用で使える関数や手続きをまとめた
自分のライブラリィにインプリメントしておくことにしました。
重ねてお礼申し上げます。
> ただ、Win7,XE4ではエラーが出ました。
Windows7,Delphi6でも正常な動作を確認しました。
ありがとうございました。
>ただ、Win7,XE4ではエラーが出ました。
以下のようにしてみてください.
//参照カウンタ対策
UniqueString(Cmd); // これを追加
if CreateProcess(nil,
以下,省略
>command.com
ついでに,参考までに,Windows Vista, Windows 7 の 64 ビット版では,
Command.com はなくなりました.
Cmd.exe を使用することになります.
Mr.XRAYさん、ありがとうございます。
UniqueString(Cmd);を追加すると正常に処理できました。
この関数は初めて見たのですが、XEでは、PChar(cmd) などを行う前に
UniqueString(Cmd) を行ったほうがいいということなのでしょうか?
これは「参照カウンタ」の問題ですね.
ということは「参照カウンタ」のことを書かないと,ということなのですが.
ググッていただくのがいいと思うのですが,ググったら,あまりいいのがないですね.
というこで,参照カウンタについて説明を書き始めたのですが,長くなってしまいました (笑)
そこで,その説明はやめて,とりあえず以下を参考にしてください.
今回は,ユニコード版の CreateProcess の問題です.
[Delphi Unicodeワールド パートIII: コードをUnicode対応にする]
http://edn.embarcadero.com/jp/article/38699
↑
ページ内を CreateProcess で検索
[各種文字列の実際]
http://ht-deko.minim.ne.jp/tech018.html
[デバッグ時に CreateProcess() や ShellExecute() でおかしくなる。 (Unicode 版 Delphi)]
http://ht-deko.minim.ne.jp/tech050.html
参照カウンタについて一番明確なのが,COM のインターフェイスを使用する時です.
AddRef (インクリメント.Ref は参照の意味でしょう)
Release (デクリメント.解放です)
C++ では明示的にこのメソッドの処理コードを書くことになります.
Delphi では,これを意識しなくても自動でやってくれます.
余談ですが,Delphi 2010 は一部のインターフェイスで,問題があって,
以下のページのコードでは,自前でやりました.
興味があったらページ内を「参照カウンタ」で検索してみてください.
本当は,継承元の AddRef, Release を実行すればいいのですが,チョンボしています.
http://mrxray.on.coocan.jp/Delphi/plSamples/947_ExplorerBrowsert.htm
# レスにも体力が必要ですな.ハハハッ.
>本当は,継承元の AddRef, Release を実行すればいいのですが,チョンボしています.
何故 -1 にしているのかは,
[各種文字列の実際]
http://ht-deko.minim.ne.jp/tech018.html
を参考にしてください.
「文字列」というオブジェクトも「COM インターフェイス」のオブジェクトも扱いは同じです.
「参照カウンタ」という数ですから.
>「参照カウンタ」の問題
というのは違います。
「参照カウンタ」は間接的には関係していますが、原因ではありません。
CreateProcessWは一部の引数に書き込み権限を要求します。
しかし定数や参照カウンタが-1の文字列が置かれているメモリ領域は読み込み専用となっています。
このためアクセス違反が出るのです。
試しに文字列定数を変数に代入し、System.pas内にあるPStrRecでキャストする等して
参照カウントを書き換えてみると分かりますが、ここは関係していません。
あくまでも元の文字列が置かれた領域のアクセス保護如何によるので、
VirtualProtectを利用して書き込み権限を与えても正しく動作するようになります。
>しかし定数や参照カウンタが-1の文字列が置かれているメモリ領域は読み込み専用となっています。
>このためアクセス違反が出るのです。
フォローありがとうございます.
>VirtualProtectを利用して書き込み権限を与えても正しく動作するようになります。
こちらの方がよさそうですね.
Mr.XRAYさん、Protectさん、ありがとうございます。
10年以上Delphi使ってますが、参照カウンタ、全く知らずに
今に至っています(^^;
正直、初耳で大変参考になりました。
ツイート | ![]() |