如何在Windows 10企业版上将应用程序作为shell替换运行

时间:2015-10-27 10:04:57

标签: windows shell powershell windows-10

我需要在运行Windows 10 Enterprise的计算机上创建一个特殊帐户。此帐户将直接在登录时启动应用程序,而不是默认shell,退出应用程序应强制计算机重新启动。

我可以使用配置控制台和锁定功能在Windows 8.1 Embedded Industry Pro上轻松完成此操作。

现在,在Windows 10上,我尝试按照technet上的两个教程WESL_UserSettingSet up a kiosk on Windows 10 Pro, Enterprise, or Education

但是,这两个教程都不起作用。我已设法执行其中描述的脚本,但它们没有效果(我已修改它们,因此它们不会删除shell集)。

最后我最终得到了以下代码:

$COMPUTER = "localhost"
$NAMESPACE = "root\standardcimv2\embedded"
$ACCOUNT_NAME = "cmp"

$ShellLauncherClass = [wmiclass]"\\$COMPUTER\${NAMESPACE}:WESL_UserSetting"


$NTUserObject = New-Object System.Security.Principal.NTAccount($ACCOUNT_NAME)
$NTUserSID = $NTUserObject.Translate([System.Security.Principal.SecurityIdentifier]).Value

$NTUser_Shell = Get-WmiObject -namespace $NAMESPACE -computer $COMPUTER -class WESL_UserSetting | 
    where {$_.Sid -eq $NTUserSID}

if ($NTUser_Shell) {
    "`Custom shell already set for [$ACCOUNT_NAME] removing it"
    $ShellLauncherClass.RemoveCustomShell($NTUserSID)
}

$restart_shell = 0
$restart_device = 1
$shutdown_device = 2

$ShellLauncherClass.SetCustomShell($NTUserSID, "cmd.exe", ($null), ($null), $restart_device)

"`nCurrent settings for custom shells:"
Get-WmiObject -namespace $NAMESPACE -computer $COMPUTER -class WESL_UserSetting | Select Sid, Shell, DefaultAction

在admin powershell中执行此脚本会产生所需的输出:

Custom shell already set for [cmp] removing it

Current settings for custom shells:

Sid                                            Shell   DefaultAction
---                                            -----   -------------
S-1-5-21-3842421150-1098587697-2315725148-1002 cmd.exe             1

但是,以'cmp'用户身份登录只会显示标准的Windows 10 shell。

为了能够运行程序而不是标准shell,我应该更改什么?

9 个答案:

答案 0 :(得分:12)

我现在遇到了同样的问题。是的,微软已经改变了更换外壳的方法。您可以安装和使用Embedded Shell Launcher根据自助服务终端模式自定义窗口。但这仅适用于企业和教育。

如果您不想购买企业版,您可以使用HKCU和HKLM中已知的注册地点。 https://msdn.microsoft.com/en-us/library/ms838576(v=WinEmbedded.5).aspx

但是等等,哦,不,因为Windows 10只能使用Microsoft签名的应用程序,所以你的普通.net应用程序没有启动,登录后屏幕仍然是黑屏。但我们已经找到了解决方法。

只需使用批处理文件作为自举。如果您将注册表项设置为批处理文件,批处理文件启动实际应用程序,那么它就像魅力一样。

@echo off
echo Bootstrapping, please wait ...
start /b "Bootstrap" "C:\vmwatcher\VMViewClientWatcher.exe"

答案 1 :(得分:6)

您是否尝试过更改用户shell?

https://msdn.microsoft.com/en-us/library/ms838576(v=WinEmbedded.5).aspx

您需要设置一些注册表项。第一个允许为用户提供唯一的shell,第二个定义启动而不是资源管理器的可执行文件。

答案 2 :(得分:4)

我想做类似的事情,我从其他答案中大量借用,但这些答案对我来说都不是一个完整的答案。这就是我最终做的事情。

  1. 创建新用户帐户
  2. 设置以下vbs脚本(主要受this thread启发)以启动shell应用程序,并将其命名为" launch.vbs"
  3. set oShell=createobject("wscript.shell") 
    sCmd="d:\launchbox\launchbox.exe" 
    oShell.run sCmd,,true 'true forces it to wait for process to finish 
    sCmd="shutdown /r /t 0" 
    oShell.run sCmd
    
    1. 以新用户身份登录

    2. 运行regedit

    3. 将名为Shell的新字符串值添加到HKEY_Current_User \ Software \ Microsoft \ Windows NT \ CurrentVersion \ Winlogon,其值为执行脚本所需的命令值:

    4. wscript d:\launchbox\launch.vbs
      
      1. 注销并以用户身份重新登录以查看其实际操作

答案 3 :(得分:3)

我认为您为用户正确设置了自定义shell,但是您可能需要激活ShellLanuncher行为。 试试这个(在你的脚本的最后):

$ShellLauncherClass.SetEnabled($TRUE)

这样,当您使用其他帐户登录时,不会启动标准的Windows 10 shell,但是(至少在我的情况下)命令行无法启动,结果是黑屏。

您仍然可以运行任务管理器并从那里运行新任务,但我不明白为什么命令行不会自动启动。

答案 4 :(得分:3)

我自己和这个人一起战斗。如果查看Windows 10 Shell Launcher的注释,它只适用于Enterprise或Education版本。如果您尝试在Home或Pro版本中使用它,它只需启动到空白屏幕。在Enterprise中使用相同的脚本,我确认工作完美......

答案 5 :(得分:1)

我遇到了同样的问题,那是因为the Script from TechNet on how to configure ShellLauncher实际启用了,然后禁用相同的Shell!

# Enable Shell Launcher

$ShellLauncherClass.SetEnabled($TRUE)

$IsShellLauncherEnabled = $ShellLauncherClass.IsEnabled()

"`nEnabled is set to " + $IsShellLauncherEnabled.Enabled

# Remove the new custom shells.

$ShellLauncherClass.RemoveCustomShell($Admins_SID)

$ShellLauncherClass.RemoveCustomShell($Cashier_SID)

# Disable Shell Launcher

$ShellLauncherClass.SetEnabled($FALSE)

$IsShellLauncherEnabled = $ShellLauncherClass.IsEnabled()

"`nEnabled is set to " + $IsShellLauncherEnabled.Enabled

我只是懒得复制并粘贴代码并期望它能够正常工作。

如果你注释掉最后十行,这个过程起作用。

记住孩子们:不要只是复制和粘贴来自陌生人的代码!

答案 6 :(得分:1)

我想首先为评论一个非常旧的线程而道歉。

在过去的 6 个月里,我一直在努力让自定义应用程序作为默认 shell 运行,并保留管理员权限。像许多人一样,这些脚本和/或命令无法正常工作,我需要一些快速、有效和简单的方法!

只需使用自定义应用程序位置替换“explorer.exe”(HKLM\SOFTWARE\Microsoft\Window NT\Winlogon\Shell)即可提供黑屏。

一种更简单且效果很好的方法是创建一个 BATCH 脚本以通过提升的 powershell 调用自定义应用程序...

powershell -nologo -noprofile -executionpolicy bypass -command "start-process -verb 'runas' -filepath <full path of custom app executable>"

通过使用此批处理脚本替换“explorer.exe”,我能够在 Windows 10 PRO 下使用非 UWP 应用成功创建自助服务终端样式锁定。

答案 7 :(得分:0)

我的拳头试图帮助我收到的很多。不是一个完整的答案,但也许足以让你到达目的地。这适用于我的“Kiosk”应用程序,该应用程序位于“我的”Windows 10 Enterprise系统上,该系统专为我的应用程序而构建。它会将你的“shell”设置为在系统启动时启动,然后启动你的click click程序。希望这会有所帮助。

//
//  ViewController.swift
//  Calculator_IOS10
//
//  Created by Theophilos Aravanis on 4/12/17.
//  Copyright © 2017 Theophilos Aravanis. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var calculatorDisplay: UILabel!

    @IBOutlet weak var discriptionDisplay: UILabel!

    @IBOutlet weak var varibleDisplay: UILabel!



    var displays: (result: Double, isPending:Bool, sequence:String, errorMessage:String?) {

        get {

            return (Double(calculatorDisplay.text!)!, false, discriptionDisplay.text!, nil)

        }

        set {

            if newValue.errorMessage != " " {
                calculatorDisplay.text = newValue.errorMessage
            } else {
                let formatter = NumberFormatter()
                formatter.numberStyle = .decimal
                formatter.maximumFractionDigits = 6
                calculatorDisplay.text = formatter.string(from:(NSNumber(value:newValue.result)))
            }
            if newValue.sequence.isEmpty {
                discriptionDisplay.text = " "
            } else {
               discriptionDisplay.text = newValue.sequence + (brain.resultIsPending ? " …" : " =")
            }

            if let varibaleValue = dictionaryForVaribles["M"] {
                let formatter = NumberFormatter()
                formatter.numberStyle = .decimal
                formatter.maximumFractionDigits = 6
                varibleDisplay.text = formatter.string(from:(NSNumber(value:varibaleValue)))
            } else {
                varibleDisplay.text = " "
            }

        } // end of set
    }

    var userInMiddleOfTyping = false

    var currentDisplay = " "

    var dictionaryForVaribles = [String:Double]()

    @IBAction func digitTouched(_ sender: UIButton) {

        let digit = sender.currentTitle!
        if userInMiddleOfTyping {
            let currentlyDisplayedText = calculatorDisplay.text!
            switch digit {
            case ".":
                if currentlyDisplayedText.contains("."){
                    calculatorDisplay.text = currentlyDisplayedText
                }
                else {
                    calculatorDisplay.text = currentlyDisplayedText + digit
                }
            case "BS":
                currentDisplay = calculatorDisplay.text!
                if currentDisplay.isEmpty == false {
                  currentDisplay.remove(at: currentDisplay.index(before: currentDisplay.endIndex))
                    if currentDisplay.isEmpty {
                        calculatorDisplay.text = "0"
                        userInMiddleOfTyping = false
                    } else {
                        calculatorDisplay.text = currentDisplay
                        userInMiddleOfTyping = true
                    }
                }
            default:
                calculatorDisplay.text = currentlyDisplayedText + digit
            }
        }
        else {
            switch digit {
            case "bs":
                break
            default:
                calculatorDisplay.text = digit
                userInMiddleOfTyping = true
            }
        }
    }

  /*  var displayValue:Double{
        get {
            return Double(calculatorDisplay.text!)!

        }
        set {
            let formatter = NumberFormatter()
            formatter.numberStyle = .decimal
            formatter.maximumFractionDigits = 6
            calculatorDisplay.text = formatter.string(from:(NSNumber(value:newValue)))
        }
    }
    var displayDescription:String{
        get {
                return discriptionDisplay.text!
        }
        set {
          discriptionDisplay.text = newValue + (brain.resultIsPending ? " …" : " =")
        }
    } */
    private var brain = CalculatorBrain()

    func showDescriptionDisplay() {
        discriptionDisplay.isHidden = false
    }
    func hideDescriptionDisplay() {
        discriptionDisplay.isHidden = true
    }

    func showVaribleDisplay() {
        varibleDisplay.isHidden = false
    }

    func hideVaribleDisplay() {
        varibleDisplay.isHidden = true
    }

    @IBAction func allClear(_ sender: UIButton) {
        hideDescriptionDisplay()
        discriptionDisplay.text = " "
        calculatorDisplay.text = "0"
        userInMiddleOfTyping = false
        brain.clearAccumulator()
    }

    @IBAction func setVarible(_ sender: UIButton) {
      let symbol = sender.currentTitle!
        brain.setOperand(variable:symbol)
    }

    @IBAction func evaluateVarible(_ sender: UIButton) {
    }

    @IBAction func performOperation(_ sender: UIButton) {
        showDescriptionDisplay()
        if userInMiddleOfTyping {
            brain.setOperand(displays.result)
            userInMiddleOfTyping = false
        }
        if let mathimaticalSymbol = sender.currentTitle {
            brain.performOperation(mathimaticalSymbol)
        }

        displays = brain.evaluateWithErrorReport(using: dictionaryForVaribles) as! (result: Double, isPending: Bool, sequence: String, errorMessage: String?)


/*        if let result = brain.result {
            displays.result = result
        }
//        if let descriptionLine = brain.line {
//            displays.sequence = descriptionLine
//        } */
    }
}

答案 8 :(得分:0)

您可以使用Windows Configuration Designer创建配置包。 当您选择“供应信息亭设备”时,该GUI将有助于创建简单的外壳替换件