28.05.2024

Kapanan sunucudan haberdar olmak

Sunucular önemli. Onlar ne zaman yeniden başlamış, sebebi neymiş gibi sorular hep var. Bu soruların cevaplarını ben daha sormadan bulacak bir yöntemim olmasını istedim. Söz konusu sunucular Windows. Linux için de benzer bir yöntem bulunabilir elbet, önemli olan mantık.

Windows'da bir zamanlanmış göre oluşturayım. D:\bildir.ps1 konumundaki powershell betiğini çalıştırsın.

$act1 = New-ScheduledTaskAction -Execute powershell.exe 
-Argument "-ExecutionPolicy Bypass -NoProfile -File D:\bildir.ps1"
-WorkingDirectory "D:\"

Tetikleyici olarak da Sistem açılışını seçeyim.

$trig1 = New-ScheduledTaskTrigger -AtStartup 

Bu işi bir kullanıcının hesabı ile değil, SYSTEM hesabı ile yapacağım. Yüksek yetkilere ihtiyacım yok, standart yetkiler yeterli.

$prin1 = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Limited 

Önce görev nesnesini oluşturup sonrasında kaydetmek istiyorum. Bu işi iki adımda yapacağım.

$tsk1  = New-ScheduledTask -Action $act1 -Principal $prin1 -Trigger $trig1
$tsk1 | Register-ScheduledTask -TaskName "YenidenbaslatmaBildirimi" -TaskPath "\Firma"

Sıra geldi D:\bildir.ps1 betiğini oluşturmaya. Bu aşamaya kadar bilgisayar çoktan yeniden başladı. Betik bize açılıştan sonra bildirim verecek. Bu amaca yönelik aşağıdaki içerik yeterli:

$tarih = Get-Date -Format "yyyy-MM-ddTHH-mm-ss"
$sunucu_adi=$env:COMPUTERNAME
$smtpParams = @{
   From = "$sunucu_adi@firma.com"
   To = "admin@firma.com"
   Body = "$tarih - $sunucu_adi yeniden basladi"
   Subject = "$sunucu_adi yeniden basladi"
   SmtpServer = "smtp.firma.com"
}
Send-MailMessage @smtpParams
Add-Content -Value "$tarih - $sunucu_adi" -Path D:\bildir.log

Bu kısmı sadece sunucunun ne zaman başladığını bildirdi. Biraz da nedene olaklanalım. Windows'da nedeni bulmak için birkaç farklı yere bakmak gerekebilir. Olası sebepler Windows Update, güç kaybı, operatör isteği veya kritik bir uygulamanın hata vermesi olabilir. Bütün bu olayları içine alan bir olay kaydı günlüğünü inceleyelim:

$olaylar = Get-WinEvent -FilterHashTable @{LogName='System';`
StartTime=(Get-Date).AddHours(-1);`
ID=19,20,21,22,26,27,41,109,1000,1001,1002,1074,1076,6005,6006,6008} -ea silent

Bazen hiçbir olay dönmeyebilir. Bu gibi durumlarda, hata vermemesi sonuna için -ea silent (-ErrorAction SilentlyContinue kısaltması) ekledim. Daha sonra bu olayların içeriklerini gönderilecek mesajın gövdesine ekleyelim. Yukarıdaki betikte mesajın gövdesi $smtpParams içinde kısa bir şekilde oluşturulmuştu. Örneği bozmamak için aşağıdaki kodu bu splat değişkeninin ardından, Send-MailMessage cmdlet'inden önce olmasını düşündüm.

foreach ($olay in $olaylar) {
    $Body += "$($olay.TimeCreated) - $($olay.Id) - $($olay.Message)"
}

Bu şekilde en üstte tarih ve saatin yanında sunucu adı ve "yeniden basladi" görünecek. Ardından son 1 saatte konuyla ilgili olabilecek tüm olay kayıtları listelenecek. Bu elbette iyileştirmeye açık.

15.05.2024

Tarayıcı savaşları

 Bugün Reddit'te aşağıdaki ekran görüntüsünü görünce şaşırdım.


Bu "kullanıcı iradesine müdahale" delilini gördükten sonra önce Linux üzerinden Bing'de yaptığım aramada benzer bir sonuç ile karşılaşmadım. Sonra Windows'da Edge ile yaptığım aramada ben de aynı şeyi gördüm:


Bu bir arama motoru. Arama terimlerine karşılık gelen en yakın sonuçları listelemesi gerek. Ama o sonuçları amacına göre değiştiriyor. İlk sıraya reklam görünümlü mesajı koyuyor: "Yeni bir web tarayıcısı indirmenize gerek yok".

İlk adımı bunun gibi görece masum minik müdahaleler sonraki adımlarda hayatımızda daha büyük etkiye sahip, daha rahatsız edici şekillerde kullanılıyor. Bakınız, Cambridge Analytica olayı. "Kullanıcı davranışında belli belirsiz bir değişikliğe sebep olabiliyorsak başarılı sayılırız" denmişti. Kullanıcı verileri kullanılmıyor gibi gelebilir belki ama Linux'ta aynı sonucu vermediğinden yola çıkarak benim işletim sistemimin Windows olmadığı bilgisini kullandı bile.

---

https://www.reddit.com/r/browsers/comments/1crs3d1/who_else_does_this/
https://www.reddit.com/r/Windows11/comments/17b3bu5/microsoft_stop_making_me_feel_bad_for_downloading/
https://www.reddit.com/r/assholedesign/comments/zz8t4i/microsoft_really_does_not_want_you_to_download/
https://www.reddit.com/r/windows/comments/12skbx9/edge_stopping_me_from_downloading_chrome/
https://www.reddit.com/r/shitposting/comments/199sxv9/edging_to_this_rn/
https://www.reddit.com/r/pcmasterrace/comments/199vks2/chat_is_this_real/
https://www.reddit.com/r/firefox/comments/11cpa98/forgot_how_pushy_edge_is_after_a_clean_install/

8.05.2024

Powershell ve Windows Firewall

Windows Firewall, Windows Advanced Firewall veya Windows Defender Firewall. Microsoft'un ürünlerine verdiği isimler bana hep garip gelmiştir. Bir müzik ve video oynatıcısı yapıp adına media player demek, mesajlaşma uygulamasına messanger, interent tarayıcılarına Internet Explorer demek... İşletim sisteminin adı zaten Windows.

Konuyu dağıtmayalım. Bugün baktığımda kullandığım bilgisayarın güvenlik duvarımda 700'den fazla kural var. En fazla 2 tanesini ben oluşturmuşumdur -belki. Üstüne ek yazılımlar kurduğumuzda daha da fazlası geliyor. Bunlar ile uğraşmak hiç kolay değil. Evet, belli kolaylıklar sağlanmış, gruplanmış. Ağlara göre sınıflandırılmış (etki alanı, özel ağ, genel ağ falan) ama yine de belli bir portu açmak için yeni bir kural mı oluştursam, yoksa var olan kurallardan biri işimi görür mü diye düşündüğüm durumlar hiç az değil. Üstüne üstlük "Gelişmiş Güvenlik Özellikli Windows Defender Güvenlik Duvarı" uygulaması da pek kullanışlı değil. İsme, adrese veya porta göre arama, sıralama, süzme yok. Ama iyi ki Powershell var!

Yeni bir bilgisayara oturduk. Tüm önyargılara rağmen ilk yapılacak iş güvenlik duvarını devreye almak. Güvenlik duvarı, bağlı olunan ağ profiline göre kuralları etkinleştiriyor. Mevcut ağ profilimize bakalım:

Get-NetConnectionProfile

Bakılacak alan NetworkCategory. Private / Public arasında geçiş yapmak için

Set-NetConnectionProfile -NetworkCategory Private

kullanabiliriz. Bu profile uyan güvenlik duvarı profilimizi görmek için

Get-NetFirewallProfile -Name Private | Select-Object Name, Enabled, DefaultInboundAction

kullanabilir, Enabled alanından etkin mi değil mi görebilir, DefaultInboundAction'dan kurala uymayan gelen trafiğe karşı varsayılan eylemini (Block olmalı) tespit edebiliriz. Genel eğilim, güvenlik duvarını etkinleştirirken bütün profilleri etkinleştirmek. Eğer yapmak istediğimiz buysa

Set-NetFirewallProfile -All -Enabled True

Burada garip olan, True değerinin bir boolean değer değil de GpoBoolean olması. Şu sayfa da dahil her yerde $True yerine True yazılmış. Tam olarak aynı şey mi, emin değilim ama şöyle birşey buldum:

$a = [Microsoft.PowerShell.Cmdletization.GeneratedTypes.NetSecurity.GpoBoolean]::True
$a -eq $True
True

yani sanki aynı şey. Bu adımlardan sonra ikinci yaptığım şey genelde bazı temel kuralları etkinleştirmek veya kontrol etmek. Örneğin söz konusu bilgisayara uzak masaüstü yapılmasını istiyorsam ilgili kuralın devrede olup olmadığını kontrol ederim. Bunun için içinde "Uzak Masaüstü*" (İngilizce bilgisayarlarda "Remote Desktop*") geçen kuralları  geçenleri ararım:

Get-NetFirewallRule -DisplayName "Uzak Masaüstü*" | ft Name, DisplayName, Enabled

Bunu dahil oldukları gruba göre arayarak da yapabilirim:

Get-NetFirewallRule -DisplayGroup "Uzak Masaüstü" | ft Name, DisplayName, Enabled

Bu kuralların hangi uygulamaya, hangi porta ve hangi uzak IP grubuna izin/engelleme verdiğini görmek için ise şu sorgu mükemmel:

Get-NetFirewallRule -DisplayGroup "Uzak Masaüstü" | 
Format-Table DisplayName,
@{N="Port";E={($_|Get-NetFirewallPortFilter).LocalPort}},
@{N="Application";E={($_|Get-NetFirewallApplicationFilter).Program}},
@{N="Address";E={($_|Get-NetFirewallAddressFilter).RemoteAddress}} -AutoSize

Benzer şekilde IIS yüklü bir bilgisayarda 80 numaralı port üzerinden HTTP hizmeti vermek için güvenlik duvarındaki kuralları kontrol etmek istersem

Get-NetFirewallRule -DisplayGroup "*World Wide Web Services*" | Ft DisplayGroup, DisplayName, Enabled

Bilgisayarımız ping'lere cevap veriyor mu diye bakmak için (İngilizce bilgisayarlarda):

Get-NetFirewallRule -DisplayName "Core Networking Diagnostics - ICMP Echo Request (ICMPv4-In)" | 
Format-Table DisplayGroup, Displayname, Profile, Enabled

ya da grup bazlı

Get-NetFirewallRule -DisplayGroup "Core Networking Diagnostics" | 
Format-Table DisplayGroup, Displayname, Profile, Enabled

Türkçe bilgisayarlarda aynısını yapmak için ise

Get-NetFirewallRule -DisplayName "Çekirdek Ağ Tanılama - ICMP Yankı İsteği (ICMPv4-Gelen)" | 
Format-Table DisplayGroup, Displayname, Profile, Enabled

grup bazlı olarak da

Get-NetFirewallRule -DisplayGroup "Çekirdek Ağ Tanılama" | 
ft DisplayGroup, DisplayName, Profile, Enabled -AutoSize

gibi birşey olabilir. Bunlardan etkinleştirmek istediklerimizi pipe ile

Get-NetFirewallRule -DisplayName "Çekirdek Ağ Tanılama - ICMP Yankı İsteği (ICMPv4-Gelen)" | 
Enable-NetFirewallRule

ya da devre dışı bırakmak için Disable-NetFirewallRule yapabiliriz. Dosya ve yazıcı paylaşımı kural grubu için sırasıyla Türkçe ve İngilizce bilgisayarlarda komudumuz şöyle olabilir:

Get-NetFirewallRule -DisplayGroup "Dosya ve Yazıcı Paylaşımı" | 
ft Displayname, DisplayGroup, Enabled, Profile -AutoSize

Get-NetFirewallRule -DisplayGroup "File and Printer Sharing" | 
ft Displayname, DisplayGroup, Enabled, Profile -AutoSize

Bütün dosya paylaşımlarını devre dışı bırakmak için

Get-NetFirewallRule -DisplayGroup "Dosya ve Yazıcı Paylaşımı" | Disable-NetFirewallRule

kullanılabilir.

Asıl kilit nokta, herhangi bir porta komuta eden bir kural var mı yok mu aramak istersek

Get-NetFirewallRule | where {($_ | Get-NetFirewallPortFilter).LocalPort -eq 9401} | select DisplayName

Kurallar etki alanı (domain), özel ağlar (private) ve genel ağlar (public) olarak kategorize edildiği için bu profile bilgisine dikkat etmek çok önemli. Özel bir ağda çalışırken genel ağ kuralı üzerinde işlem yaparsak etkili olmayacaktır.

Bunları Get-* komutları ile mevcut durumu görmek üzerine komutlardı. Bir de kurallarda toplu değişiklik yapalım. Örneğin DisplayGroup özelliği "Dosya ve Yazıcı Paylaşımı" olan kural gruplarını sadece belli IP'lerden erişilebilecek şekilde ayarlayalım. Önce "Dosya ve Yazıcı Paylaşımı" DisplayGroup'una dahil kuralların IP adresi kısıtlaması var mı, bakalım:

Get-NetFirewallRule -DisplayGroup "Dosya ve Yazıcı Paylaşımı" | 
Format-Table Enabled, DisplayName, Profile, 
@{N="Scope";E={($_|Get-NetFirewallAddressFilter).RemoteAddress}} -Autosize

Bu şekilde hedef kural grubumun tam olarka istediğim kurallar olduğundan emin olabilirim. Hedef kural grubum basit bir şekilde DisplayName veya DisplayGroup ile ifade edilebilecek grup ise basitçe

Set-NetFirewallRule -DisplayGruop "Dosya ve Yazıcı Paylaşımı" -RemoteAddress 192.168.1.28

gibi bir komutla bu kurala uzaktan erişebilecek bilgisayarların IP adreslerini seçebilirim.

Bu arada LocalSubnet bilgisayarın yerel ağındaki IPv4 ve IPv6 altağını kapsar. Sadece IPv4 için LocalSubnet4, veya sadece IPv6 için LocalSubnet6 kullanılabilir:
Set-NetFirewallRule -DisplayGruop "Dosya ve Yazıcı Paylaşımı" -RemoteAddress LocalSubnet4

Daha karmaşık bir senaryomuz varsa, örneğin domain profilinde ve sadece etkinleştirilmiş kural alt grubununa uzaktan erişebilecek bilgisayarın IP adresini kısıtlamak için

Get-NetFirewallRule -DisplayGroup "Dosya ve Yazıcı Paylaşımı" | 
where {$_.Enabled -eq $true -and $_.Profile -eq "Domain"} | 
Set-NetFirewallRule -RemoteAddress 192.168.1.28

6.05.2024

ProfileNameServer

Etki alanı üyesi taşınabilir bir bilgisayarımız var. Etki alanı dışına çıktığında bir wifi ağına bağlanarak işlem yapamadığına dair bir şikayet geldi. İncelediğimde

ipconfig /all

ile listelenen DNS suncuların hala (yerel ağın dışında bir wifi'a bağlıydı ve bu wifi kendi DNS sunucusunu bildiriyordu) etki alanımızın (aslında halen kullanılmayan eski) sunucularının olduğunu gördüm. Ağ adaptörlerinin hiçbirinde bu IP adresleri girilmemişti. Nereden gelebilir acaba diye registry'de yaptığım bir aramada HKLM\System\CurrentControlSet\Services\Tcpip\Parameters\Interface altında bazı GUID'lerin altında ProfileNameServer adında bazı girişlerin olduğunu ve bu girişlerin içinde eski sunucularımıza ait DNS girişlerinin halen yer aldığını farkettim. Garip bir şekilde bu durumu yaşayan başka [1], [2] insanlar da varmış. Çözüm elle bu değerleri silmek ya da 

Set-DHCPClientServerAddress -InterfaceIndex xx -ResetServerAddress

kullanarak bunu işi Powershell'e yaptırmak.

---

[1] https://learn.microsoft.com/en-us/answers/questions/828532/static-dns-server-address-returning
[2] https://www.qbitnetworking.com/blog-posts/windows-10-wifi-dns-server-address-stuck-wifi-is-connected-but-no-internet

30.04.2024

Uzak masaüstü bağlantıları

Microsoft-Windows-TerminalServices-LocalSessionManager/Operational altındaki olaylar hakkında bulduğum birkaç küçük ipucu:

Genelde gördüğüm 3 olay var:

24: Session disconnected

25: Session reconnected

40: Yukarıdaki 2 olaya eşlik eden, reconnection ve disconnection olaylarına ait reason code'lar verililir.

Reason code yeni yapılan bağlantının ya da kesilen bağlantının sebebi hakkında bazı küçük bilgiler içerir. Şu ve şu sitelere göre:

0: Kullanıcı uzak masaüstü oturumunu pencerenin çarpısına basarak (ya da ağ bağlantı sorunu sebebiyle) kapatmıştır. Bu olay 24 olayı ile birlikte olur. Ayrıntılar 24 olayında belirtilir.

5: Oturumun kapanma sebebi bu oturumun başka bir oturumla değiştirilmesi. Aslında şu demek; disconnect edilmiş bir oturum kalmıştı, yeniden o oturuma bağlanıldı.

Ben sık görmesem de başka reason code'lar:

2: Admin kullanıcı oturumunu sonlandırdı (Admin has signed off/ Terminated the user session.)

3: Boş kalma süresi aşıldı (Idle Session Timer limit reached.)

4: İzin verilen süreden daha fazla bağlanıldığı için sonlandırıldı.

6: Hafıza yetersiz

7: Sunucu bağlantıya izin vermedi

8: Sunucu güvenlik sebebiyle bağlantıyı reddetti.

9: Sunucu güvenlik sebebiyle bağlantıyı reddetti.

10: Kullanıcı adı ve şifrenin tekrar girilmesi gerekli

11: Kullanıcı etkinliği sebebiyle sonlanma.

12: Kullanıcı oturumu kapattı.

---

https://community.spiceworks.com/t/remote-desktop-services-disconnect-code/375433/7

https://learn.microsoft.com/tr-tr/windows/win32/termserv/extendeddisconnectreasoncode?redirectedfrom=MSDN


25.04.2024

schtasks.exe ile zamanlanmış görevler

Bir RDP oturum açması sırasında çalışacak bir görev oluşturmak

    schtasks /Create 
        /TN "MyEventTask"
        /SC ONEVENT
        /EC "Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational"
        /MO "*[System[Provider[@Name='Microsoft-Windows-TerminalServices-RemoteConnectionManager'] and (EventID=1149)]]"
        /TR "powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\1149.ps1"

Kullanıcı oturum açsa da açmasa da çalışacak bir görev için

    schtasks /Create 
        /TN "MyEventTask"
        /SC ONEVENT
        /EC "Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational"
        /MO "*[System[Provider[@Name='Microsoft-Windows-TerminalServices-RemoteConnectionManager'] and (EventID=1149)]]"
        /TR "powershell.exe -ExecutionPolicy Bypass -File C:\Scripts\1149.ps1"
        /RU SYSTEM
        /NP

Mevcut görevlerin hepsini export etmek için

schtasks /Query /XML /TN "*"

Sonra bu xml dosyalarından tekrar görevler oluşturmak için

dir *.xml | % { schtasks /Create 
/XML $_.FullName
/TN "$_.Name.replace('.xml','')"
/RU "new_username"
/RP "new_password"

Bir görev nesnesini parola kaydetmeden oluşturmak için /NP anahtarı,

Tam tersi, parolayı belirlemek için /RP <parola>

Görevin yetki seviyesini belirlemek için /RL <LIMITED|HIGHEST>

ONSTART, ONLOGON, ONEVENT olayları için rastgele bir gecikme ayarlamak için ise /DELAY mmmm:ss kullanılabilir.

---

https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/schtasks-query

24.04.2024

Powershell ile ileri seviye zamanlanmış görevler

Zamanlanmış görevler sadece belli periyotlarda değil, belli olayların ardından çalışacak şekilde de oluşturulabiliyor. Ama bunu Powershell ile yapmak biraz meşakkatli. Oturum açma sonrasında ve bilgisayarın başlangıcında çalıştırılacak görevler için trigger nesneleri aşağıdaki gibi oluşturulabiliyor:
$trig1 = New-ScheduledTaskTrigger -AtLogon
$trig2 = New-ScheduledTaskTrigger -AtStartup

Ancak örneğin uzakmasaüstü bağlantısı ardından (TerminalServices-RemoteConnectionManager/Operational / Id:1149) çalışacak bir trigger'ın oluşturulması şu şekilde:

$class = Get-CimClass -Class "MSFT_TaskEventTrigger" -ClassRoot "Root/Microsoft/Windows/TaskScheduler"
$trig3 = $class | New-CimInstance -ClientOnly
$trig3.Subscription = "<QueryList>`
<Query>`<Select Path='Microsoft-Windows-TerminalServices-RemoteConnectionManager/Operational'>`
    *[System[Provider[@Name='Microsoft-Windows-TerminalServices-RemoteConnectionManager'] `
    and (EventID=1149)]]</Select></Query></QueryList>"

(satırlar ` karakteri ile bölünmüştür) ile, ve görev oluşturulması/değişikliğinde çalışacak görevin trigger'ı

$trigger1 = Get-CimClass -ClassName "MSFT_TaskRegistrationTrigger" -Namespace "Root/Microsoft/Windows/TaskScheduler"

ile yapılabiliyor.

Bir powershell görevinin gizli oluşturulması için

$settings = New-ScheduledTaskSettings -Hidden

kullanılabilir. Belli bir kullanıcının masaüstü ile etkileşime geçebilmesi için

$principal = New-ScheduledTaskPrinciple -UserId "makine\kullanidi" -LogonType Interactive

seçilmeli. LogonType alanı için Group, Interactive, InteractiveOrPassword, None, Password, S4U, ServiceAccount gibi değerler var. Bir görevin kullanıcı oturum açsın ya da açmasın çalışmasını sağlamak için S4U kullanılabilir.

$principal = New-ScheduledTaskPrinciple -UserId "makine\kullanidi" -LogonType S4U

Çalışacak görevin yetkileri RunLevel ile belirtilebilir (Limited/Highest):

$principal = New-ScheduledTaskPrinciple -UserId "makine\kullanidi" -LogonType Interactive -RunLevel Highest

LocalService veya System kullanıcıları ile bir görev çalıştırmak için

$principal = New-ScheduledTaskPrincipal -UserId "LOCALSERVICE" -LogonType ServiceAccount
$principal = New-ScheduledTaskPrincipal -UserId "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount

ve hatta bir grup yetkileriyle görev planlamak için

$principal = New-ScheduledTaskPrincipal -GroupId "BUILTIN\Administrators" -RunLevel Highest

kullanılabilir. Mevcut bir zamanlanmış görevin trigger'larından birini değiştirmek için aşağıdaki yöntem kullanılabilir:

$task = Get-ScheduledTask -TaskName "Gorev1"
$trig = $task.Triggers
$trig.Repetition.Duration = $null
$trig.Repetition.StopAtDurationEnd=$false
Set-ScheduledTask -InputObject $task

Birden fazla trigger eklemek için iki trigger bir dizi olarak atanabilir:

$task.Triggers = ($trigger1, $trigger2)

gibi. Bir dizüstü bilgisayardaki görevin bataryadan çalışıldığı anda bile çalışmasını sağlamak veya uyku kipindeki bilgisayarları uyandırmak için için New-ScheduledTaskSettingsSet'in seçenekleri kullanılabilir.

Tekrarlayacak görevler için RepetitionInterval'a aşağıdaki gibi New-TimeSpan cmdlet'i ile zaman aralığı atanabilir.

$trig1 = New-ScheduledTaskTrigger -At 13:30 -Once -RepetitionInterval (New-TimeSpan -Hours 1)

benzer şekilde -RandomDelay parametresine de bir New-TimeSpan ile zaman aralığı verilmeli

$trig1 = New-ScheduledTaskTrigger -AtLogon -RandomDelay (New-TimeSpan -Minutes 5)

gibi. Sonradan değiştirmek için ise

$task.Triggers[0].Repetition.RepetitionInterval = New-TimeSpan -Hours 1

"No mapping between account names and security IDs was done" gibi bir hata, var olmayan bir kullanıcı belirtildiğini gösterir. Runlevel için Highest seçilecekse Powershell penceresi de yüksek yetkilerle açılmış olmalı. Varsayılan ayarlara sahip bir görev için New-ScheduledTaskSettings ve New-ScheduledTaskPrincipal kullanmak gerekli değil.

Bir olay sonrasında çalıştırılacak görev oluşturduğumuzda çalışmıyorsa yapılabilecek şey göreve ait trigger'ı kontrol etmek olabilir. Genelde provider name yanlış yazdığımda yaşadığım bir hataydı. Kontrol etmek için trigger'ı açtığımda aşağıdaki gibi bir ekranla karşılaştım:


Source (ya da provider) kısmında "Microsoft-Windows-TerminalServices-TaskScheduler" ve "TaskScheduler" seçenekleri var. TaskScheduler gibi Uygulama ve Hizmet Günlüklerinde genelde birden fazla Source olmıyor. Bunlardan üstteki yanlış yazılmış. Ama gerek schtasks.exe gerek powershell ile görev oluştururken sadece TaskSheduler yazmak da yetmiyor. Bunun yerine tam yolu "Microsoft-Windows-TaskScheduler" olarak yazmak gerek, burada o sadece TaskScheduler olarak kısaltılabilir.

Zamanlanmış görevin en son çalıştığı zamanı, döndüğü durum/hata kodu gibi bilgilerini görmek için ise

Get-ScheduledTask -Taskname "gorev-1" | Get-ScheduledTaskInfo 

kullanılabilir. Dönülen hata/durum kodları ile ilgili şu bilgiler var:

0 => "Görev başarıyla çalıştırıldı",
1 => "Yanlış veya bilinmeyen görev",
2 => "Dosya bulunamadı.",
a => "Ortam yanlış.",
00041300 => "Bir sonraki döngüde çalışmaya hazır",
00041301 => "Görev şu anda çalışıyor",
00041302 => "Görev devre dışı",
00041303 => "Görev henüz hiç çalışmadı",
00041304 => "Bu görev için başka çalışma zamanı planlanmamış",
00041305 => "Görevin çalışması için bir veya daha fazla özellik atanmamış",
00041306 => "Görevin çalışması kullanıcı tarafından sonlandırıldı",
00041307 => "Ya trigger yok, ya da trigger'lar devre dışı",
00041308 => "Trigger'larda zaman belirtilmemiş",
80010002 => "Call was canceled by the message filter",
80041309 => "Görevin trigger'ı bulunamadı",
8004130A => "One or more of the properties required to run this task have not been set.",
8004130B => "There is no running instance of the task.",
8004130C => "The Task Scheduler service is not installed on this computer.",
8004130D => "The task object could not be opened.",
8004130E => "The object is either an invalid task object or is not a task object.",
8004130F => "No account information could be found in the Task Scheduler security database for the task indicated.",
80041310 => "Unable to establish existence of the account specified.",
80041311 => "Corruption was detected in the Task Scheduler security database",
80041312 => "Task Scheduler security services are available only on Windows NT.",
80041313 => "The task object version is either unsupported or invalid.",
80041314 => "The task has been configured with an unsupported combination of account settings and run time options.",
80041315 => "The Task Scheduler Service is not running.",
80041316 => "The task XML contains an unexpected node.",
80041317 => "The task XML contains an element or attribute from an unexpected namespace.",
80041318 => "The task XML contains a value which is incorrectly formatted or out of range.",
80041319 => "The task XML is missing a required element or attribute.",
8004131A => "The task XML is malformed.",
0004131B => "The task is registered, but not all specified triggers will start the task.",
0004131C => "The task is registered, but may fail to start.Batch logon privilege needs to be enabled for the task principal.",
8004131D => "The task XML contains too many nodes of the same type.",
8004131E => "The task cannot be started after the trigger end boundary.",
8004131F => "An instance of this task is already running.",
80041320 => "The task will not run because the user is not logged on.",
80041321 => "The task image is corrupt or has been tampered with.",
80041322 => "The Task Scheduler service is not available.",
80041323 => "The Task Scheduler service is too busy to handle your request. Please try again later.",
80041324 => "The Task Scheduler service attempted to run the task, but the task did not run due to one of the constraints in the task definition.",
00041325 => "The Task Scheduler service has asked the task to run.",
80041326 => "The task is disabled.",
80041327 => "The task has properties that are not compatible with earlier versions of Windows.",
80041328 => "The task settings do not allow the task to start on demand.",
80070002 :  The system cannot find the file specified - (https://itexperience.net/0xfffd0000-in-task-scheduler-when-running-powershell-script/, 800070002 yaziyordu)
800710e0 :  Operator refures the request. Check permissions. see https://windowsreport.com/0x800710e0/
8007010b :  Start in folder is incorrect
C000013A => "The application terminated as a result of a CTRL+C.",
C0000142 => "The application failed to initialize properly.",
FFFD0000 :  Path error, possibly for powershell scripts

---

https://xplantefeve.io/posts/SchdTskOnEvent

https://richardspowershellblog.wordpress.com/2014/09/12/multiple-triggers-on-a-scheduled-task/

https://www.pdq.com/powershell/set-scheduledtask/

https://lazyadmin.nl/powershell/how-to-create-a-powershell-scheduled-task/