簡體   English   中英

如何以編程方式關閉或打開“Windows 功能”

[英]How can I programmatically turn off or on 'Windows Features'

當我嘗試更新 Windows 功能時; 當我將 UseShellExecute 更新為“true”時; “進程 object 必須將 UseShellExecute 屬性設置為 false 才能重定向 IO 流。” 我得到一個錯誤。 當我將其設置為 False 時; 無法更新。 我該怎么做? 你有什么其他的建議?

 static void InstallIISSetupFeature()
        {
            var featureNames = new List<string>() {

                 "IIS-WebServerRole",
                "IIS-WebServer",
                "IIS-CommonHttpFeatures",
                "IIS-HttpErrors",
                "IIS-HttpRedirect",
                "IIS-ApplicationDevelopment",
                "IIS-Security",
                "IIS-RequestFiltering",
                "IIS-NetFxExtensibility",
                "IIS-NetFxExtensibility45",
                "IIS-HealthAndDiagnostics",
                "IIS-HttpLogging",
                "IIS-LoggingLibraries",
                "IIS-RequestMonitor",
                "IIS-HttpTracing",
                "IIS-URLAuthorization",
                "IIS-IPSecurity",
                "IIS-Performance",
                "IIS-HttpCompressionDynamic",
                "IIS-WebServerManagementTools",
                "IIS-ManagementScriptingTools",
                "IIS-IIS6ManagementCompatibility",
                "IIS-Metabase",
                "IIS-HostableWebCore","IIS-StaticContent", 
                "IIS-DefaultDocument",
                "IIS-DirectoryBrowsing",
                "IIS-WebDAV",
                "IIS-WebSockets",
                "IIS-ApplicationInit",
                "IIS-ASPNET",
                "IIS-ASPNET45",
                "IIS-ASP",
                "IIS-CGI",
                "IIS-ISAPIExtensions",
                "IIS-ISAPIFilter",
                "IIS-ServerSideIncludes",
                "IIS-CustomLogging",
                "IIS-BasicAuthentication",
                "IIS-HttpCompressionStatic",
                "IIS-ManagementConsole",
                "IIS-ManagementService",
                "IIS-WMICompatibility",
                "IIS-LegacyScripts",
                "IIS-LegacySnapIn",
                "IIS-FTPServer",
                "IIS-FTPSvc",
                "IIS-FTPExtensibility",
                "IIS-CertProvider",
                "IIS-WindowsAuthentication",
                "IIS-DigestAuthentication",
                "IIS-ClientCertificateMappingAuthentication",
                "IIS-IISCertificateMappingAuthentication",
                "IIS-ODBCLogging",
                "NetFx4-AdvSrvs",
                "NetFx4Extended-ASPNET45",
                "NetFx3",
                "WAS-WindowsActivationService",
                "WCF-HTTP-Activation",
                "WCF-HTTP-Activation45",
                "WCF-MSMQ-Activation45",
                "WCF-NonHTTP-Activation",
                "WCF-Pipe-Activation45",
                "WCF-TCP-Activation45",
                "WCF-TCP-PortSharing45",
                "WCF-Services45",
            };
               ManagementObjectSearcher obj = new ManagementObjectSearcher("select * from Win32_OperatingSystem");
                foreach (ManagementObject wmi in obj.Get())
                {
                    string Name = wmi.GetPropertyValue("Caption").ToString();
                    Name = Regex.Replace(Name.ToString(), "[^A-Za-z0-9 ]", "");
                    if (Name.Contains("Server 2008 R2") || Name.Contains("Windows 7"))
                    {
                        featureNames.Add("IIS-ASPNET");
                        featureNames.Add("IIS-NetFxExtensibility");
                        featureNames.Add("WCF-HTTP-Activation");
                        featureNames.Add("WCF-MSMQ-Activation");
                        featureNames.Add("WCF-Pipe-Activation");
                        featureNames.Add("WCF-TCP-Activation");
                        featureNames.Add("WCF-TCP-Activation");
                    }
                    string Version = (string)wmi["Version"];
                    string Architecture = (string)wmi["OSArchitecture"];
                }         
            foreach (var featureName in featureNames)
            {
                Run(string.Format("dism/online/Enable-Feature:{0}", featureName));
            }
         
        }  
        static void Run(string arguments)
        {
            try
            {
                string systemPath = Path.Combine(Environment.ExpandEnvironmentVariables("%windir%"), "system32");

                var dism = new Process();
                dism.StartInfo.WorkingDirectory = systemPath;
                dism.StartInfo.Arguments = arguments;
                dism.StartInfo.FileName = "dism.exe";
                dism.StartInfo.Verb = "runas";

                dism.StartInfo.UseShellExecute = true;
                dism.StartInfo.RedirectStandardOutput = true;
                dism.Start();
                var result = dism.StandardOutput.ReadToEnd();
                dism.WaitForExit();
            }
            catch (Exception ex)
            {
            }

        }`

我嘗試用 dism.exe 和 cmd.exe 更新功能,當它給出授權錯誤時,我使用了 Verb 屬性`

  • 由於.Verb = "RunAs"的使用需要.UseShellExecute = true ,並且由於后者不能與RedirectStandardOutput = true結合使用,因此您無法直接在 memory 中捕獲提升的進程'output。

    • 似乎系統本身,通過安全意識的設計,阻止非提升的進程直接捕獲提升的進程' output
  • 解決方法通過shell間接啟動目標可執行文件(在您的情況下為dism.exe ),然后使用后者的重定向功能( >文件中捕獲目標可執行文件的 output(總是),如下所示。

string systemPath = Path.Combine(Environment.ExpandEnvironmentVariables("%windir%"), "system32");

// Create a temp. file to capture the elevated process' output in.
string tempOutFile = Path.GetTempFileName();

var dism = new Process();
dism.StartInfo.WorkingDirectory = systemPath;
// Use cmd.exe as the executable, and pass it a command line via /c
dism.StartInfo.FileName = "cmd.exe" ;
// Use a ">" redirection to capture the elevated process' output.
// Use "2> ..." to also capture *stderr* output.
// Append "2>&1" to capture *both* stdout and stderr in the file targeted with ">"
dism.StartInfo.Arguments = 
  String.Format(
    "/c {0} {1} > \"{2}\"", 
    "dism.exe", arguments, tempOutFile
  );
dism.StartInfo.Verb = "RunAs";
dism.StartInfo.UseShellExecute = true;

dism.Start();
dism.WaitForExit();
// Read the temp. file in which the output was captured...
var result = File.ReadAllText(tempOutFile);
// ... and delete it.
File.Delete(tempOutFile);

首先,您可以使用WindowsPrincipal::IsInRole()來檢查您是否正在運行提升權限。 有關詳細信息,請參閱Microsoft Learn

其次,這可能是使用本機 PS 比 cmdlet 方法更容易的情況之一(誠然,仍然不是很好)。

如果腳本應該在客戶端和服務器操作系統上運行:使用Get-WmiObjectGet-CimInstance獲取對您正在運行的內容的引用。 ActiveDirectory 也有該信息(在 operatingSystem 屬性中)。

對於服務器,請使用 ServerManager 模塊中Get-WindowsFeature 對於客戶端,在 DISM 模塊中使用帶有開關-OnlineGet-WindowsOptionalFeature ,如果您確實需要支持早於 6.3.xxxx 的操作系統,可以從擁有它的機器上復制並添加到$Env:Path before C:\Windows和 C:\Windows\System32。

對於任一平台,只需傳遞要配置的功能列表。

如果在(二進制)cmdlet 中您必須調用外部工具,那么它們的優勢就基本消失了。 可以使用托管的 API 訪問 Windows CBS 來避免這種情況,但即便如此,基於腳本的方法也能更快地獲得更多結果,尤其是因為您只需將dism.exe快速包裝在一起即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM