2011-05-23 23 views
5

這一個看起來微不足道,但答案几乎沒有我了。更改調用進程的環境變量

我有一個Windows批處理文件,它調用一個C#程序來做一個額外的驗證,不能在批處理文件中完成。驗證完成後,我需要將狀態和字符串返回到調用shell。

現在返回值是微不足道的,我的C#控制檯應用程序只是設置一個返回值(如果您願意,退出代碼)。我認爲這個字符串也是小菜一碟。我試圖定義使用一個新的shell變量:

Environment.SetEnvironmentVariable("ERR", "Some text"); 

此調用應該(和做)的當前進程中定義一個shell變量 - 那就是創建的變量非常的C#程序。只要C#應用程序終止,創建C#應用程序的shell就會對該變量一無所知,該值就會丟失。所以......一個沒有特別用處的調用......根本......除非可能我從C3應用程序創建了一個子進程,否則它可能會繼承我的變量。

SetEnvironmentVariable調用的EnvironmentVariableTarget.Machine和EnvironmentVariableTarget.User目標也不能解決問題,因爲只有新創建的進程纔會從註冊表中獲取這些新值。

因此,唯一可行的解​​決方案,我能想到的是:

  • 寫入stdout
  • 寫入到文件
  • 編碼額外的含義爲返回值

前兩個有點醜陋,最後一個有其侷限性和問題。

任何其他想法(如何在父進程中設置shell變量)?也許這樣的shell變量修改是一個安全問題(想想PATH)...

謝謝你的時間。

回答

0

我的英美菸草公司有點生疏,但我認爲可以通過%ERRORLEVEL%從外部運行的流程中檢索「退出」代碼。如果是這樣的情況下,通過

Environment.Exit(123); // where 123 = error code 

一定要退出你的程序不能添加任何的消息,所以你必須做的是,在.bat文件。

如果不是這種情況,stdout可能是最好的方法。

+0

確實如此。控制檯應用程序的結果通常通過返回碼返回。顯然''Environment.Exit()'在框架上有點粗糙......所以一個簡單的'return x'是首選的方法。但是,我想知道是否有一種方法可以將**另一個值**推送到父shell環境中。例如錯誤代碼123以字符串形式的解釋... 我現在正在使用stdout ...將其重定向到一個文件,將其讀回到一個shell var,刪除該文件...略有骯髒,但它的作品。 – JamesH 2011-05-23 14:10:42

1

如果你想放一些輸出值到一個變量在批處理,您可以使用下面的結構:

6.1.7601 

「有usebackq」的意思是:我的操作系統

FOR /F "usebackq tokens=4 delims=\[\] " %i IN (`ver`) DO set VERSION=%i 
ECHO %VERSION% 

輸出我們使用的是後引號,它能夠在用雙引號括起來的命令中使用文件集。你可能不需要這個。 '令牌'表示結果字符串數組中要選擇的索引(它可以是範圍M-N)。如果您需要跳過行,請使用'skip = X')。'delims'是要使用的字符串分隔符(如.Net中的字符串Split())。

你會把你的控制檯應用程序,而不是'ver',並調整分隔符和令牌以匹配您的具體輸出。如果你有更多的變數需要填寫,你需要做的更復雜一點,但這應該是一個好的開始。

2

您所要求的是能夠隨意寫入正在運行的進程的內存空間。出於好的原因,沒有SeDebugPrivilege,這是不可能的。

您列出的三種解決方案中的任何一種都可以使用。標準輸出是與批處理腳本進行通信的標準方式。

順便說一句,你正在編寫一個Windows批處理文件。我很確定這艘船已經航行了「有點難看」。

3

我和Ryan有同樣的問題,作爲解決方法時唯一想到的就是在出錯時編寫一個批處理來設置變量並從批處理中調用它。

ConsoleApplication1.exe中:

'put some sensible code here 
'put result in variable myResult 
Dim myResult As String = Guid.NewGuid().ToString("D").ToUpperInvariant() 
Console.WriteLine("Normal output from the consonle app") 
Console.Error.WriteLine("@ECHO OFF") 
Console.Error.WriteLine("SET zzzResult={0}", myResult) 

TEST.CMD(調用批處理):

@ECHO OFF 
:Jump to folder of batch file 
PUSHD %~d0%~p0 

:Define a temp file 
SET zzzTempFile=%TEMP%\TMP%Random%.CMD 

:Call .NET console app 
ConsoleApplication1.exe 2>%zzzTempFile% 

:Call the generated batch file 
CALL %zzzTempFile% 

:Clean up temp file 
DEL %zzzTempFile% 

:Clean up variable 
SET zzzTempFile= 

:Do something with the result 
ECHO Yeah, we finally got it! 
ECHO: 
ECHO The value is "%zzzResult%". 
ECHO: 

:Clean up result variable 
SET zzzResult= 

:Go back to original folder 
POPD 

這應該做的伎倆。是的,我知道這是一箇舊的帖子,瑞恩現在正在解決其他問題,但可能還有其他人在那裏有同樣的問題...

0

在最近,我絆倒這個自己,想出了這種方法。我所做的是使用Process類運行bat文件,即

// Spawn your process as you normally would... but also have it dump the environment varaibles 
Process process = new Process(); 
process.StartInfo.FileName = mybatfile.bat; 
process.StartInfo.Arguments = @"&&set>>envirodump.txt"; 
process.StartInfo.UseShellExecute = false; 
process.StartInfo.RedirectStandardOutput = true; 
process.StartInfo.RedirectStandardError = false; 
process.Start(); 
string output = process.StandardOutput.ReadToEnd(); 
process.WaitForExit(); 

// Read the environment variable lines into a string array 
string[] envirolines = File.ReadAllLines("envirodump.txt"); 
File.Delete("envirodump.txt"); 

// Now simply set the environment variables in the parent process 
foreach(string line in a) 
{ 
    string var = line.Split('=')[0]; 
    string val = line.Split('=')[1]; 
    Environment.SetEnvironmentVariable(var, val); 
} 

這似乎對我有用。這不是最乾淨的方法,但會起作用。 :)