Heh nice to read your problems are, of course, not your fault. Step 1) Post that image does not work Step 2) Blame others for why that is the case ` Lastly, I recommend absolutely no 3rd party tools to do image optimizations unless an end-user has no intention of actually using proper scripts and projects. Anything and everything is available natively through 2 types of code; both easy to learn: C# and PowerShell. You can do anything from granting system rights and access token privileges by adjusting process privileges and user rights on the LSA namespace. You can use Wimgapi.dll to do more than any 3rd party tool can do with a WIM using the Interop namespace. An example of 3 of my cmdlets (the C# code is omitted because the last thing we need is you trying these advanced functions and ruining the hardware (yes, you can ruin your hardware with user right and process privilege token granting) Code: Function Grant-Privilege { <# .SYNOPSIS Grants system privileges by adjusting Access Tokens. .DESCRIPTION Grants system-level access by adjusting the process privileges associated with their corresponding Access Tokens. .PARAMETER Privilege The name of the process privilege to grant. .EXAMPLE PS C:\> Grant-Privilege -Privilege SeBackupPrivilege .NOTES To prevent accidental system inoperability, use privileges sparingly. Only grant process privileges when needed. .INPUTS PRIVILEGES_LSA.AccessTokens Privilege #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'The process token privilege to grant.')][ValidateSet('SeAssignPrimaryTokenPrivilege', 'SeAuditPrivilege', 'SeBackupPrivilege', 'SeChangeNotifyPrivilege', 'SeCreateGlobalPrivilege', 'SeCreatePagefilePrivilege', 'SeCreatePermanentPrivilege', 'SeCreateSymbolicLinkPrivilege', 'SeCreateTokenPrivilege', 'SeDebugPrivilege', 'SeEnableDelegationPrivilege', 'SeImpersonatePrivilege', 'SeIncreaseBasePriorityPrivilege', 'SeIncreaseQuotaPrivilege', 'SeIncreaseWorkingSetPrivilege', 'SeLoadDriverPrivilege', 'SeLockMemoryPrivilege', 'SeMachineAccountPrivilege', 'SeManageVolumePrivilege', 'SeProfileSingleProcessPrivilege', 'SeRelabelPrivilege', 'SeRemoteShutdownPrivilege', 'SeRestorePrivilege', 'SeSecurityPrivilege', 'SeShutdownPrivilege', 'SeSyncAgentPrivilege', 'SeSystemEnvironmentPrivilege', 'SeSystemProfilePrivilege', 'SeSystemtimePrivilege', 'SeTakeOwnershipPrivilege', 'SeTcbPrivilege', 'SeTimeZonePrivilege', 'SeTrustedCredManAccessPrivilege', 'SeUndockPrivilege', 'SeUnsolicitedInputPrivilege')][ValidateNotNullOrEmpty()][Alias('Token')][PRIVILEGES_LSA.AccessTokens[]]$Privilege ) Begin { $ErrorMessage = $_.Exception.Message } Process { ForEach ($Token in $Privilege) { Try { [PRIVILEGES_LSA.TokenAdjustor]::GrantPrivilege($Token) } Catch [System.ComponentModel.Win32Exception] { Throw [System.ComponentModel.Win32Exception]::New("$($ErrorMessage) ($Token)", $_.Exception) } } } } Function Revoke-Privilege { <# .SYNOPSIS Revokes system privileges by adjusting Access Tokens. .DESCRIPTION Revokes system-level access by adjusting the process privileges associated with their corresponding Access Tokens. .PARAMETER Privilege The name of the process privilege to revoke. .EXAMPLE PS C:\> Revoke-Privilege -Privilege SeBackupPrivilege .NOTES To prevent accidental system inoperability, use privileges sparingly. Always revoke process privileges that are no longer needed. .INPUTS PRIVILEGES_LSA.AccessTokens Privilege #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'The process token privilege to revoke.')][ValidateSet('SeAssignPrimaryTokenPrivilege', 'SeAuditPrivilege', 'SeBackupPrivilege', 'SeChangeNotifyPrivilege', 'SeCreateGlobalPrivilege', 'SeCreatePagefilePrivilege', 'SeCreatePermanentPrivilege', 'SeCreateSymbolicLinkPrivilege', 'SeCreateTokenPrivilege', 'SeDebugPrivilege', 'SeEnableDelegationPrivilege', 'SeImpersonatePrivilege', 'SeIncreaseBasePriorityPrivilege', 'SeIncreaseQuotaPrivilege', 'SeIncreaseWorkingSetPrivilege', 'SeLoadDriverPrivilege', 'SeLockMemoryPrivilege', 'SeMachineAccountPrivilege', 'SeManageVolumePrivilege', 'SeProfileSingleProcessPrivilege', 'SeRelabelPrivilege', 'SeRemoteShutdownPrivilege', 'SeRestorePrivilege', 'SeSecurityPrivilege', 'SeShutdownPrivilege', 'SeSyncAgentPrivilege', 'SeSystemEnvironmentPrivilege', 'SeSystemProfilePrivilege', 'SeSystemtimePrivilege', 'SeTakeOwnershipPrivilege', 'SeTcbPrivilege', 'SeTimeZonePrivilege', 'SeTrustedCredManAccessPrivilege', 'SeUndockPrivilege', 'SeUnsolicitedInputPrivilege')][ValidateNotNullOrEmpty()][Alias('Token')][PRIVILEGES_LSA.AccessTokens[]]$Privilege ) Begin { $ErrorMessage = $_.Exception.Message } Process { ForEach ($Token in $Privilege) { Try { [PRIVILEGES_LSA.TokenAdjustor]::RevokePrivilege($Token) } Catch [System.ComponentModel.Win32Exception] { Throw [System.ComponentModel.Win32Exception]::New("$($ErrorMessage) ($Token)", $_.Exception) } } } } Another one of my cmdlets allowing full native ownership and access control of any object, no matter who owns it or its subkeys/child-keys. As you can see, when the script cannot take ownership of a file (leaf), it automatically moves up in the directory chain and takes control of the directory recursively instead. Code: Function Grant-AccessPermissions { <# .SYNOPSIS Grants file and folder access control permissions. .DESCRIPTION Grants system-level file and folder access by enabling access token process privileges. .PARAMETER Path The path to the file or folder access is to be granted to. .PARAMETER Account The account name that will be granted access. .PARAMETER Recurse Allows for access control permissions to be recursively granted on directories and subdirectories. .EXAMPLE PS C:\> Grant-AccessPermissions -Path 'File' .EXAMPLE PS C:\> Grant-AccessPermissions -Path 'Folder' -Recurse .EXAMPLE PS C:\> Grant-AccessPermissions -Path 'File' -Account 'DomainName\DomainAccount' .EXAMPLE PS C:\> $Path = "C:\Mount\Users\Default\ProgramData" PS C:\> Get-ChildItem -Path $Path -Recurse -Force | Grant-AccessPermissions .NOTES The BUILTIN\Administrators account is the default user-account access is granted to. #> [CmdletBinding(SupportsShouldProcess = $true)] Param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = 'The path to the file or folder to take ownership of.')][ValidateScript({ If (Test-Path -Path $_) { $_ } Else { Throw "$_ is not a valid path." } })][Alias('FullName')][string]$Path, [Parameter(HelpMessage = 'The name of the account that will be granted ownership.')][Alias('User')][string]$Account = "BUILTIN\Administrators", [Parameter(HelpMessage = 'Enables recursive ownership granting of directories and folders.')][switch]$Recurse ) Begin { If ($PSBoundParameters['Debug']) { $DebugPreference = 'Continue' } [PRIVILEGES_LSA.TokenAdjustor]::GrantPrivilege("SeRestorePrivilege") [PRIVILEGES_LSA.TokenAdjustor]::GrantPrivilege("SeBackupPrivilege") [PRIVILEGES_LSA.TokenAdjustor]::GrantPrivilege("SeTakeOwnershipPrivilege") } Process { ForEach ($File in $Path) { Write-Verbose "Processing: $File" $DirOwner = New-Object System.Security.AccessControl.DirectorySecurity $DirOwner.SetOwner([System.Security.Principal.NTAccount]$Account) $FileOwner = New-Object System.Security.AccessControl.FileSecurity $FileOwner.SetOwner([System.Security.Principal.NTAccount]$Account) $DirACL = New-Object System.Security.AccessControl.DirectorySecurity $FileACL = New-Object System.Security.AccessControl.FileSecurity $Rule = New-Object System.Security.AccessControl.FileSystemAccessRule("BUILTIN\Administrators", "FullControl", "ContainerInherit,ObjectInherit", "InheritOnly", "Allow") $FileACL.AddAccessRule($Rule) $DirACL.AddAccessRule($Rule) Try { $File = Get-Item -LiteralPath $File -Force If (!($File.PSIsContainer)) { If ($PSCmdlet.ShouldProcess($File, "Grant File Permissions")) { Try { $File.SetAccessControl($FileOwner) } Catch { Write-Warning "Failed to grant full permissions on $($File.FullName). Attempting to grant full permissions on $($File.Directory.FullName)." $File.Directory.SetAccessControl($FileACL) $File.SetAccessControl($FileOwner) } } } Else { If ($PSCmdlet.ShouldProcess($File, "Grant Directory Permissions")) { Try { $File.SetAccessControl($DirOwner) } Catch { Write-Warning "Failed to grant full directory permissions on $($File.FullName). Attempting to grant full directory permissions on $($File.Parent.FullName)." $File.Parent.SetAccessControl($DirACL) $File.SetAccessControl($DirOwner) } } If ($Recurse) { [void]$PSBoundParameters.Remove('Path') Get-ChildItem $File -Recurse -Force | Grant-AccessPermissions @PSBoundParameters } } } Catch { Write-Warning "$($File): $($_.Exception.Message)" } } } End { [PRIVILEGES_LSA.TokenAdjustor]::RevokePrivilege("SeRestorePrivilege") [PRIVILEGES_LSA.TokenAdjustor]::RevokePrivilege("SeBackupPrivilege") [PRIVILEGES_LSA.TokenAdjustor]::RevokePrivilege("SeTakeOwnershipPrivilege") } } Here we can natively take control of any protected registry key: Code: Function Grant-RegistryAccess { <# .SYNOPSIS Grants access to protected registry keys by adjusting Access Tokens. .DESCRIPTION Grants system-level registry key access by adjusting the process privileges associated with their corresponding Access Tokens. .PARAMETER Hive The name of the registry hive where the subkey resides. .PARAMETER SubKey The path to the subkey that will be granted access to. .EXAMPLE PS C:\> Grant-RegistryAccess -Hive HKLM -SubKey "SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing" .NOTES This returns ownership back to the original system owner after access has been granted and the subkey has been modified. This is to reduce the changes of broken or invalid account SIDs from cumulating. #> [CmdletBinding()] Param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)][ValidateSet('HKCR', 'HKCU', 'HKLM')][string]$Hive, [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)][string]$SubKey ) Begin { [PRIVILEGES_LSA.TokenAdjustor]::GrantPrivilege("SeRestorePrivilege") [PRIVILEGES_LSA.TokenAdjustor]::GrantPrivilege("SeBackupPrivilege") [PRIVILEGES_LSA.TokenAdjustor]::GrantPrivilege("SeTakeOwnershipPrivilege") } Process { Switch ($Hive.ToString().ToLower()) { "HKCR" { $Key = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey($SubKey, [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, [System.Security.AccessControl.RegistryRights]::TakeOwnership) } "HKCU" { $Key = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey($SubKey, [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, [System.Security.AccessControl.RegistryRights]::TakeOwnership) } "HKLM" { $Key = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($SubKey, [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree, [System.Security.AccessControl.RegistryRights]::TakeOwnership) } } $ACL = $Key.GetAccessControl([System.Security.AccessControl.AccessControlSections]::None) $AdminSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544") $Account = $AdminSID.Translate([System.Security.Principal.NTAccount]) $ACL.SetOwner($Account) $Key.SetAccessControl($ACL) $ACL = $Key.GetAccessControl() $Rights = [System.Security.AccessControl.RegistryRights]"FullControl" $Inheritance = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit" $Propagation = [System.Security.AccessControl.PropagationFlags]"None" $Control = [System.Security.AccessControl.AccessControlType]"Allow" $Rule = New-Object System.Security.AccessControl.RegistryAccessRule($Account, $Rights, $Inheritance, $Propagation, $Control) $ACL.SetAccessRule($Rule) $Key.SetAccessControl($ACL) $Key.Close() Switch ($Hive.ToString().ToLower()) { "HKCR" { $Key = "HKLM:\SOFTWARE\Classes\$SubKey" } "HKCU" { $Key = "HKCU:\$SubKey" } "HKLM" { $Key = "HKLM:\$SubKey" } } } End { [PRIVILEGES_LSA.TokenAdjustor]::RevokePrivilege("SeRestorePrivilege") [PRIVILEGES_LSA.TokenAdjustor]::RevokePrivilege("SeBackupPrivilege") [PRIVILEGES_LSA.TokenAdjustor]::RevokePrivilege("SeTakeOwnershipPrivilege") } } Sorry, no, I do not need to run scripts with BIN files full of 20+ programs to do things I can write in 15 minutes myself and wrap in a PowerShell script. And this is why my images work - everything is always done natively, using the .NET framework, and properly using system objects.
Easy to learn and invaluable in its ability to wrap any other programming language and compile it directly within the function for use. If you cannot do something with PowerShell natively, you can simply wrap simple C# code as a New-Object and add it to the function. This is how we attain access to protected namespaces to adjust BIOS settings directly from the OS itself and deploy BIOS settings over a network. A snippit: Code: Add-Type @" using System; namespace PRIVILEGES_LSA { using System.Runtime.InteropServices; using System.Security; using System.Management; using System.Runtime.CompilerServices; using System.ComponentModel; using LSA_HANDLE = IntPtr; public enum AccessTokens { SeAssignPrimaryTokenPrivilege, // Replace a process-level token. SeAuditPrivilege, // Generate security audits. SeBackupPrivilege, // Back up files and directories. SeChangeNotifyPrivilege, // Bypass traverse checking. SeCreateGlobalPrivilege, // Create global objects. SeCreatePagefilePrivilege, // Create a pagefile. SeCreatePermanentPrivilege, // Create permanent shared objects. SeCreateSymbolicLinkPrivilege, // Create symbolic links. SeCreateTokenPrivilege, // Create a token object. SeDebugPrivilege, // Debug programs. SeEnableDelegationPrivilege, // Enable computer and user accounts to be trusted for delegation. SeImpersonatePrivilege, // Impersonate a client after authentication. SeIncreaseBasePriorityPrivilege, // Increase scheduling priority. SeIncreaseQuotaPrivilege, // Adjust memory quotas for a process. SeIncreaseWorkingSetPrivilege, // Increase a process working set. SeLoadDriverPrivilege, // Load and unload device drivers. SeLockMemoryPrivilege, // Lock pages in memory. SeMachineAccountPrivilege, // Add workstations to domain. SeManageVolumePrivilege, // Perform volume maintenance tasks. SeProfileSingleProcessPrivilege, // Profile single process. SeRelabelPrivilege, // Modify an object label. SeRemoteShutdownPrivilege, // Force shutdown from a remote system. SeRestorePrivilege, // Restore files and directories. SeSecurityPrivilege, // Manage auditing and security log. SeShutdownPrivilege, // Shut down the system. SeSyncAgentPrivilege, // Synchronize directory service data. SeSystemEnvironmentPrivilege, // Modify firmware environment values. SeSystemProfilePrivilege, // Profile system performance. SeSystemtimePrivilege, // Change the system time. SeTakeOwnershipPrivilege, // Take ownership of files or other objects. SeTcbPrivilege, // Act as part of the operating system. SeTimeZonePrivilege, // Change the time zone. SeTrustedCredManAccessPrivilege, // Access Credential Manager as a trusted caller. SeUndockPrivilege, // Remove computer from docking station. SeUnsolicitedInputPrivilege // Read unsolicited input from a terminal device. } For obvious reasons I am hesitant to post the full C# methods because access rights and token privileges can brick devices if you do not know what you're doing since they can directly interact with hardware. However, I'm always willing to do so privately.
I still have much to learn. I do so by studying and googling code. Trying scripts, and finding what works. I plug away until it works.
You can also wrap within wrapped code (i.e. using the Win32 wrapper allows token adjustment on current processes in order to use them as a script runs). Code: internal sealed class Win32Token { [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool AdjustTokenPrivileges ( IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen ); [DllImport("kernel32.dll", ExactSpelling = true)] internal static extern IntPtr GetCurrentProcess(); [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)] internal static extern bool OpenProcessToken ( IntPtr h, int acc, ref IntPtr phtok ); [DllImport("advapi32.dll", SetLastError = true)] internal static extern bool LookupPrivilegeValue ( string host, string name, ref long pluid ); [DllImport("kernel32.dll", ExactSpelling = true)] internal static extern bool CloseHandle ( IntPtr phtok ); } But, hey, it's fun to use batch scripts because you can press buttons and stuff, right? Sorry, we're not in 1998 anymore.
Well, what's strange is that finally someone understands the problems I had some months ago and doesn't say the fault is mine. Ok, but isn't it strange a PowerShell scrip to remove apps like the Store and Calculator ones breaks the OS? Good for you. Heh, nice you finally understood the fault wasn't, of course, mine. How can I post it since I no longer had it? I was talking about the problems I had months ago when I registered in this forum and you didn't understand. One of the problems I still have is that I'm unable to remove (let alone uninstall) some things I have in the start menu without making a clean install like the Windows Defender Security Center, Connect, Photos and Mixed Reality Portal apps. Will you still blame me? Do you expect me to understand what I have to do with that? Weren't you who told me I was a noob?
Well, it could be a hardware problem because with an untouched ISO it is not possible to have so many problems with simple tasks. But "in other PCs" does not make sense would be very unlucky. Test these memory modules and download a new ISO by disengagement of consciousness in the most do not know how I can help.
You can definitely use it to learn. It will auto-complete lines of code for you using the variables you've been assigning. It has a very easy function creator to learn how to create your own advanced functions. The object on the left are all selectable and it gives detailed information about each object/cmdlet/module/etc. and examples of how they can be used in basic and advanced scripts. You can create full projects and GUI programs. It creates all manifest files for you automatically when you create your own modules allowing cmdlet/module exporting, and supplies its own console for debugging the script (it runs as if it was doing so in the regular environment, and outputs the process percentages required by the system to run the script, syntax errors and errors sending/receiving pipe-line objects. oscdimg for ISO creation? Nah...use the .NET framework: Code: Begin { ($CP = New-Object System.CodeDom.Compiler.CompilerParameters).CompilerOptions = '/unsafe' if (!('ISOFile' -as [type])) { Add-Type -CompilerParameters $CP -TypeDefinition @' public class ISOFile { public unsafe static void Create(string Path, object Stream, int BlockSize, int TotalBlocks) { int bytes = 0; byte[] buf = new byte[BlockSize]; var ptr = (System.IntPtr)(&bytes); var o = System.IO.File.OpenWrite(Path); var i = Stream as System.Runtime.InteropServices.ComTypes.IStream; if (o != null) { while (TotalBlocks-- > 0) { i.Read(buf, BlockSize, ptr); o.Write(buf, 0, bytes); } o.Flush(); o.Close(); } } } '@ } If ($Bootable) { If ('BDR', 'BDRE' -contains $Media) { Write-Warning "$Image is incompatible with $Bootable" } ($Stream = New-Object -ComObject ADODB.Stream -Property @{ Type = 1 }).Open() $Stream.LoadFromFile((Get-Item -LiteralPath $Bootable).Fullname) ($Boot = New-Object -ComObject IMAPI2FS.BootOptions).AssignBootImage($Stream) } $MediaType = @('UNKNOWN', 'CDROM', 'CDR', 'CDRW', 'DVDROM', 'DVDRAM', 'DVDPLUSR', 'DVDPLUSRW', 'DVDPLUSR_DUALLAYER', 'DVDDASHR', 'DVDDASHRW', 'DVDDASHR_DUALLAYER', 'DISK', 'DVDPLUSRW_DUALLAYER', 'HDDVDROM', 'HDDVDR', 'HDDVDRAM', 'BDROM', 'BDR', 'BDRE') etc. etc. Anyways, I digress...All these will be in the optimization project I post within the next week (still being debugged by a handful of people).
Which memory modules? Anyway, how can I start by at least removing this start menu apps from the start menu without doing a clean install? Is it possible to reinstall the Windows Photo Viewer even after it was removed by MSMG ToolKit or NTLite?
Agreed. Point being, it's best to use one optimizing script/program for the optimization of your image. If you start with MSMG, stick with MSMG (aside from non-critical clean-up like CPL link removal and the like). NTLite is a nice program, but there's way too much missing data about many of the critical system features it removes and other info is sometimes ambiguous. MSMG you can look at the code and see what it's doing...IMO being able for people to see the actual code being used is critical to having a trusted tool and in accordance with the mentality anyone who writes pretty much anything stands by: Open Source enforces trust (so long as the processes are safe, too, of course). Hell, even Microsoft made PowerShell open source!
Hence why I use the word "optimize" and "optimizations" primarily when referring to images I create and why I've harped about the force removal of Component Packages for months. 99.9% of removals are completely unnecessary but some people aim for these tiny "Wimboot-like" Wim files like they get a medal for the smallest system image.
That's why I said it would be very unlucky. Before continuing with the tweaks it would be better to find out the cause of this otherwise you will be walking in circles without leaving the place.