simpleshare-contextwindows/Freigabe-Hinzufuegen.ps1

376 lines
13 KiB
PowerShell

#Requires -Version 5.1
param(
[Parameter(Mandatory=$true)]
[string]$Path
)
$ErrorActionPreference = "Stop"
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
function Get-Config {
$configPaths = @(
"$env:APPDATA\FreigabeKontextmenue\config.json",
"$env:ProgramData\FreigabeKontextmenue\config.json"
)
foreach ($configPath in $configPaths) {
if (Test-Path $configPath) {
return Get-Content $configPath -Raw | ConvertFrom-Json
}
}
throw "Konfiguration nicht gefunden. Bitte zuerst installieren!"
}
function Get-UNCPath {
param([string]$LocalPath)
$drive = Split-Path -Path $LocalPath -Qualifier
$driveLetter = $drive.TrimEnd(':')
$netUse = net use 2>$null | Where-Object { $_ -match "^\s*\w*\s+$driveLetter`:" }
if ($netUse) {
$parts = $netUse -split '\s+'
foreach ($part in $parts) {
if ($part -match '^\\\\') {
$uncRoot = $part
$relativePath = $LocalPath.Substring($drive.Length)
return Join-Path $uncRoot $relativePath
}
}
}
$psDrive = Get-PSDrive -Name $driveLetter -ErrorAction SilentlyContinue
if ($psDrive -and $psDrive.DisplayRoot) {
$relativePath = $LocalPath.Substring($drive.Length)
return Join-Path $psDrive.DisplayRoot $relativePath
}
$wmiDrive = Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceID='$drive'" -ErrorAction SilentlyContinue
if ($wmiDrive -and $wmiDrive.ProviderName) {
$relativePath = $LocalPath.Substring($drive.Length)
return Join-Path $wmiDrive.ProviderName $relativePath
}
$computerName = $env:COMPUTERNAME
$adminShare = "\\$computerName\$driveLetter`$"
$relativePath = $LocalPath.Substring($drive.Length)
return Join-Path $adminShare $relativePath
}
function Get-DomainUsers {
$users = @()
try {
$searcher = [adsisearcher]"(&(objectCategory=person)(objectClass=user))"
$searcher.PageSize = 1000
$searcher.PropertiesToLoad.AddRange(@("samaccountname", "displayname", "mail"))
# NetBIOS-Domänennamen ermitteln
$rootDSE = [ADSI]"LDAP://RootDSE"
$domainDN = $rootDSE.defaultNamingContext
$domainSearcher = [adsisearcher]"(&(objectClass=domain))"
$domainSearcher.SearchRoot = [ADSI]"LDAP://$domainDN"
$domainResult = $domainSearcher.FindOne()
$netbiosDomain = $null
# NetBIOS-Name aus Partitions holen
$configDN = $rootDSE.configurationNamingContext
$partSearcher = [adsisearcher]"(&(objectClass=crossRef)(nCName=$domainDN))"
$partSearcher.SearchRoot = [ADSI]"LDAP://CN=Partitions,$configDN"
$partResult = $partSearcher.FindOne()
if ($partResult -and $partResult.Properties["netbiosname"]) {
$netbiosDomain = $partResult.Properties["netbiosname"][0]
}
# Fallback: Aus USERDOMAIN
if (-not $netbiosDomain) {
$netbiosDomain = $env:USERDOMAIN
}
$results = $searcher.FindAll()
foreach ($result in $results) {
$samAccount = $result.Properties["samaccountname"][0]
$displayName = if ($result.Properties["displayname"]) { $result.Properties["displayname"][0] } else { $samAccount }
$qualifiedName = "$netbiosDomain\$samAccount"
$users += [PSCustomObject]@{
SamAccountName = $samAccount
DisplayName = $displayName
FullName = "$displayName ($samAccount)"
QualifiedName = $qualifiedName
Domain = $netbiosDomain
IsLocal = $false
}
}
} catch {
# Fallback auf lokale Benutzer (kein AD verfügbar)
$localUsers = Get-LocalUser -ErrorAction SilentlyContinue | Where-Object { $_.Enabled }
foreach ($user in $localUsers) {
$users += [PSCustomObject]@{
SamAccountName = $user.Name
DisplayName = if ($user.FullName) { $user.FullName } else { $user.Name }
FullName = if ($user.FullName) { "$($user.FullName) ($($user.Name))" } else { $user.Name }
QualifiedName = "$env:COMPUTERNAME\$($user.Name)"
Domain = $env:COMPUTERNAME
IsLocal = $true
}
}
}
return $users | Sort-Object DisplayName
}
function Show-UserSelectionDialog {
param([array]$Users)
$form = New-Object System.Windows.Forms.Form
$form.Text = "Benutzer ausw$([char]0x00E4)hlen - Freigabe"
$form.Size = New-Object System.Drawing.Size(450, 530)
$form.StartPosition = "CenterScreen"
$form.FormBorderStyle = "FixedDialog"
$form.MaximizeBox = $false
$lblSearch = New-Object System.Windows.Forms.Label
$lblSearch.Text = "Suchen:"
$lblSearch.Location = New-Object System.Drawing.Point(10, 15)
$lblSearch.Size = New-Object System.Drawing.Size(50, 20)
$form.Controls.Add($lblSearch)
$txtSearch = New-Object System.Windows.Forms.TextBox
$txtSearch.Location = New-Object System.Drawing.Point(65, 12)
$txtSearch.Size = New-Object System.Drawing.Size(355, 20)
$form.Controls.Add($txtSearch)
$listBox = New-Object System.Windows.Forms.ListBox
$listBox.Location = New-Object System.Drawing.Point(10, 45)
$listBox.Size = New-Object System.Drawing.Size(410, 330)
$listBox.Font = New-Object System.Drawing.Font("Segoe UI", 10)
$form.Controls.Add($listBox)
$script:allUsers = $Users
foreach ($user in $Users) {
$listBox.Items.Add($user.FullName) | Out-Null
}
$txtSearch.Add_TextChanged({
$searchText = $txtSearch.Text.ToLower()
$listBox.Items.Clear()
foreach ($user in $script:allUsers) {
if ($user.FullName.ToLower().Contains($searchText) -or
$user.SamAccountName.ToLower().Contains($searchText)) {
$listBox.Items.Add($user.FullName) | Out-Null
}
}
})
$chkFullPath = New-Object System.Windows.Forms.CheckBox
$chkFullPath.Text = "Kompletten Pfad in Verkn$([char]0x00FC)pfungsname schreiben"
$chkFullPath.Location = New-Object System.Drawing.Point(10, 385)
$chkFullPath.Size = New-Object System.Drawing.Size(410, 25)
$chkFullPath.Font = New-Object System.Drawing.Font("Segoe UI", 9)
$form.Controls.Add($chkFullPath)
$lblExample = New-Object System.Windows.Forms.Label
$lblExample.Text = "(z.B. 'Mandanten - S - Schmidt - Lohn' statt nur 'Lohn')"
$lblExample.Location = New-Object System.Drawing.Point(27, 408)
$lblExample.Size = New-Object System.Drawing.Size(400, 20)
$lblExample.ForeColor = [System.Drawing.Color]::Gray
$lblExample.Font = New-Object System.Drawing.Font("Segoe UI", 8)
$form.Controls.Add($lblExample)
$okBtn = New-Object System.Windows.Forms.Button
$okBtn.Text = "Freigeben"
$okBtn.Location = New-Object System.Drawing.Point(240, 450)
$okBtn.Size = New-Object System.Drawing.Size(85, 30)
$okBtn.Enabled = $false
$okBtn.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okBtn
$form.Controls.Add($okBtn)
$cancelBtn = New-Object System.Windows.Forms.Button
$cancelBtn.Text = "Abbrechen"
$cancelBtn.Location = New-Object System.Drawing.Point(335, 450)
$cancelBtn.Size = New-Object System.Drawing.Size(85, 30)
$cancelBtn.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $cancelBtn
$form.Controls.Add($cancelBtn)
$listBox.Add_SelectedIndexChanged({
$okBtn.Enabled = $listBox.SelectedIndex -ge 0
})
$listBox.Add_DoubleClick({
if ($listBox.SelectedIndex -ge 0) {
$form.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.Close()
}
})
$script:selectedUser = $null
$script:useFullPath = $false
if ($form.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK -and $listBox.SelectedIndex -ge 0) {
$selectedText = $listBox.SelectedItem
$script:selectedUser = $script:allUsers | Where-Object { $_.FullName -eq $selectedText } | Select-Object -First 1
$script:useFullPath = $chkFullPath.Checked
}
return @{
User = $script:selectedUser
UseFullPath = $script:useFullPath
}
}
function Add-FreigabePermission {
param(
[string]$TargetPath,
[string]$QualifiedUserName
)
try {
$acl = Get-Acl -Path $TargetPath
$rights = [System.Security.AccessControl.FileSystemRights]::FullControl
$inheritance = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit
$propagation = [System.Security.AccessControl.PropagationFlags]::None
$type = [System.Security.AccessControl.AccessControlType]::Allow
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($QualifiedUserName, $rights, $inheritance, $propagation, $type)
$acl.AddAccessRule($rule)
Set-Acl -Path $TargetPath -AclObject $acl
return $true
} catch {
throw "Fehler beim Setzen der Berechtigungen: $_"
}
}
function Create-Shortcut {
param(
[string]$TargetPath,
[string]$ShortcutPath
)
$shell = New-Object -ComObject WScript.Shell
$shortcut = $shell.CreateShortcut($ShortcutPath)
$shortcut.TargetPath = $TargetPath
$shortcut.Save()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($shell) | Out-Null
}
function Save-FreigabeInfo {
param(
[string]$TargetPath,
[string]$UserName
)
$metaDir = if (Test-Path "$env:ProgramData\FreigabeKontextmenue") {
"$env:ProgramData\FreigabeKontextmenue\meta"
} else {
"$env:APPDATA\FreigabeKontextmenue\meta"
}
if (-not (Test-Path $metaDir)) {
New-Item -Path $metaDir -ItemType Directory -Force | Out-Null
}
$pathHash = [System.BitConverter]::ToString([System.Security.Cryptography.MD5]::Create().ComputeHash([System.Text.Encoding]::UTF8.GetBytes($TargetPath))).Replace("-","")
$metaFile = Join-Path $metaDir "$pathHash.json"
$meta = @{
TargetPath = $TargetPath
Users = @()
}
if (Test-Path $metaFile) {
$existing = Get-Content $metaFile -Raw | ConvertFrom-Json
$meta.Users = @($existing.Users)
}
if ($UserName -notin $meta.Users) {
$meta.Users += $UserName
}
$meta | ConvertTo-Json | Set-Content -Path $metaFile -Encoding UTF8
}
try {
$config = Get-Config
$basePath = $config.LinkBasePath
if (-not (Test-Path $Path)) {
throw "Der Pfad existiert nicht: $Path"
}
$users = Get-DomainUsers
if ($users.Count -eq 0) {
throw "Keine Benutzer gefunden!"
}
$dialogResult = Show-UserSelectionDialog -Users $users
if (-not $dialogResult.User) {
exit 0
}
$selectedUser = $dialogResult.User
$useFullPath = $dialogResult.UseFullPath
$userName = $selectedUser.SamAccountName
$userFolder = Join-Path $basePath $userName
if (-not (Test-Path $userFolder)) {
New-Item -Path $userFolder -ItemType Directory -Force | Out-Null
}
$uncPath = Get-UNCPath -LocalPath $Path
# Verknuepfungsname erstellen
if ($useFullPath) {
# Kompletten Pfad verwenden: \\server\Mandanten\S\Schmidt\Lohn -> Mandanten - S - Schmidt - Lohn
$pathForName = $uncPath
# UNC-Prefix und Servernamen entfernen
if ($pathForName -match '^\\\\[^\\]+\\(.+)$') {
$pathForName = $Matches[1]
}
# Backslashes durch " - " ersetzen
$itemName = $pathForName -replace '\\', ' - '
} else {
$itemName = Split-Path -Path $Path -Leaf
}
# Ungueltige Zeichen fuer Dateinamen entfernen/ersetzen
# Verboten in Windows-Dateinamen: \ / : * ? " < > |
$itemName = $itemName -replace '[\\/:*?"<>|]', '_'
$shortcutPath = Join-Path $userFolder "$itemName.lnk"
$counter = 1
while (Test-Path $shortcutPath) {
$baseName = $itemName
$shortcutPath = Join-Path $userFolder "$baseName ($counter).lnk"
$counter++
}
Create-Shortcut -TargetPath $uncPath -ShortcutPath $shortcutPath
Add-FreigabePermission -TargetPath $Path -QualifiedUserName $selectedUser.QualifiedName
Save-FreigabeInfo -TargetPath $Path -UserName $selectedUser.QualifiedName
[System.Windows.Forms.MessageBox]::Show(
"Freigabe erfolgreich erstellt!`n`nBenutzer: $($selectedUser.DisplayName)`nVerkn$([char]0x00FC)pfung: $shortcutPath`nUNC-Pfad: $uncPath",
"Freigabe erfolgreich",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Information
)
} catch {
[System.Windows.Forms.MessageBox]::Show(
"Fehler: $($_.Exception.Message)",
"Fehler bei Freigabe",
[System.Windows.Forms.MessageBoxButtons]::OK,
[System.Windows.Forms.MessageBoxIcon]::Error
)
exit 1
}