PowerShell GUI - Nasıl başlanır?
Son birkaç yıldır birçok PowerShell betiği oluşturdum. Hepsinin tek amacı BT çalışmamı mümkün olduğunca otomatikleştirmekti. Ancak bu hafta kullanıcıların kendileri tarafından çalıştırılabilecek bir komut dosyası oluşturmam gerekiyordu. Kullanıcılar ve komut satırı da en iyi kombinasyon değil; o yüzden gelin PowerShell GUI'yi kullanmaya bir göz atalım.
Komut dosyası oluşturma söz konusu olduğunda PowerShell'i hepimiz basitliği ve verimliliği nedeniyle seviyoruz, ancak normal kullanıcılar için CLI ile çalışmak alışık oldukları bir şey değil. Bu yazımda betiğiniz için nasıl basit bir GUI oluşturabileceğinizi anlatacağım ve temel engelleri aşmanızda size yardımcı olacağım.
Örnek proje
Bu yazıda örnek olarak kendi projelerimden birini kullanacağım, bu yüzden önce çözmem gereken sorundan biraz bahsedeyim.
Bir inşaat şirketinde çalışıyorum ve şantiyelerimiz veri merkezine 4G IPVPN ağı üzerinden bağlı. Çift yerelleştirme nedeniyle yazıcıları bir yazdırma sunucusuyla dağıtamıyoruz.
Kullanıcılarımız yazıcıyı kendileri kurabilirler ancak yazdırma sunucusunda listelenmedikleri için yazıcıyı kolayca arayabilir. Bir TCP/IP bağlantı noktası oluşturmaları, yazıcının IP Adresini bulmaları, sürücüyü seçmeleri ve bir yazıcı adı vermeleri gerekecektir.
Bunu arka planda yapmak için uzaktan çalıştırabileceğim bir PowerShell betiği oluşturdum, ancak bu onların beni aramasını gerektiriyordu, böylece betiği arka planda çalıştırabilirdim. Artık tüm yazıcıları kurabilirdim, ancak bu yalnızca kafa karıştırıcı olur ve uzun bir yazıcı listesiyle sonuçlanır.
Bu yüzden PowerShell betiğinin yalnızca yazıcı modeline, IP Adresine ve bir isme ihtiyacı olduğunu düşündüm. Kullanıcının bir model seçip bir adı girebilmesi için IP Adresini arayabiliriz. Beni haftada 2 aramadan kurtarıyorsun.
PowerShell GUI'sinin temelleri
Form oluşturmaya başlamadan önce PowerShell betiğinin sırayla çalıştırıldığını bilmek önemlidir. Yani formunuzu tanımlayın ve gösterin. Ancak formu görüntüledikten sonra herhangi bir kod, siz formu kapatana kadar yürütülmeyecektir.
Bu, çözmem 30 dakikamı alan bir şey… PowerShell'de formu gösterip altındaki girişi yapabileceğimi düşündüm.
Formu oluşturma
Boş bir formla başlıyoruz. Öncelikle .Net Windows’u ekliyoruz. Formlar. Ayrıca formun boyutunu (genişlik, yükseklik), başlık ve arka plan rengini tanımlamamız gerekiyor. Aşağıdaki kodu kopyalayıp PowerShell ISE'ye yapıştırın ve çalıştır'a tıklayın.
# Init PowerShell Gui
Add-Type -AssemblyName System.Windows.Forms
# Create a new form
$LocalPrinterForm = New-Object system.Windows.Forms.Form
# Define the size, title and background color
$LocalPrinterForm.ClientSize = '500,300'
$LocalPrinterForm.text = "LazyAdmin - PowerShell GUI Example"
$LocalPrinterForm.BackColor = "#ffffff"
# Display the form
[void]$LocalPrinterForm.ShowDialog()Aşağıda buna benzer basit bir form göreceksiniz:
Formunuza öğeler ekleme
Formumuza elementler ekleyebiliriz. Bunlar bilgileri görüntülemek ve kullanıcı girdisini toplamak için kullanılabilir. Girişin yeri, sol taraftaki ve üst taraftaki noktalara/piksellere dayanmaktadır. Yani 20,50 konumu sol taraftan 20 piksel, üst taraftan ise 50 puntodur.
Formlarımızda kullanabileceğimiz aşağıdaki unsurlara sahibiz:
- TextBox (kullanıcı girişi almak için)
- Etiket
- Düğme
- Resim Kutusu
- Onay Kutusu
- ComboBox (Açılır liste)
- Liste Görünümü
- Liste Kutusu
- Radyo Düğmesi
- Paneli
- Grup Kutusu (Öğeleri birlikte gruplamak için)
- İlerleme Çubuğu
- DataGridView
Öyleyse formumuzda bazı öğeler oluşturalım. Aşağıdaki kodu scriptinize ekleyin. ShowDialog'un betiğinizin sonunda olduğundan emin olun.
# Create a Title for our form. We will use a label for it.
$Titel = New-Object system.Windows.Forms.Label
# The content of the label
$Titel.text = "Adding new printer"
# Make sure the label is sized the height and length of the content
$Titel.AutoSize = $true
# Define the minial width and height (not nessary with autosize true)
$Titel.width = 25
$Titel.height = 10
# Position the element
$Titel.location = New-Object System.Drawing.Point(20,20)
# Define the font type and size
$Titel.Font = 'Microsoft Sans Serif,13'
# Other elemtents
$Description = New-Object system.Windows.Forms.Label
$Description.text = "Add a new construction site printer to your computer. Make sure you are connected to the network of the construction site."
$Description.AutoSize = $false
$Description.width = 450
$Description.height = 50
$Description.location = New-Object System.Drawing.Point(20,50)
$Description.Font = 'Microsoft Sans Serif,10'
$PrinterStatus = New-Object system.Windows.Forms.Label
$PrinterStatus.text = "Status:"
$PrinterStatus.AutoSize = $true
$PrinterStatus.location = New-Object System.Drawing.Point(20,115)
$PrinterStatus.Font = 'Microsoft Sans Serif,10,style=Bold'
$PrinterFound = New-Object system.Windows.Forms.Label
$PrinterFound.text = "Searching for printer..."
$PrinterFound.AutoSize = $true
$PrinterFound.location = New-Object System.Drawing.Point(75,115)
$PrinterFound.Font = 'Microsoft Sans Serif,10'
# ADD OTHER ELEMENTS ABOVE THIS LINE
# Add the elements to the form
$LocalPrinterForm.controls.AddRange(@($Titel,$Description,$PrinterStatus,$PrinterFound))
# THIS SHOULD BE AT THE END OF YOUR SCRIPT FOR NOW
# Display the form
[void]$LocalPrinterForm.ShowDialog()
Burada gördüğünüz her unsurun yaratıldığıdır. Bunların hepsi basit metin veya etiket öğeleridir. Her öğenin genişliğini ve yüksekliğini tanımlayabilirsiniz, ancak içeriğiniz daha uzunsa öğe yalnızca kısmen görüntülenecektir. Dolayısıyla, Otomatik Boyutlandırma'yı doğru olarak ayarladığınızda, kullanıcının etiketin tamamını okuyabileceğinden emin olursunuz.
Her öğeye bir konum verilir; ilk rakam sol taraftaki piksel sayısı, ikinci rakam ise üst taraftaki piksel sayısıdır.
Sonuç şu şekilde görünecektir:
Açılır liste kullanma
Kullanıcımızın yazıcı üreticisini seçmesi gerekiyor, yalnızca iki marka kullanıyoruz, bu yüzden radyo düğmesi de işe yarayabilir. Yazıcının özel modelini bilmeme gerek kalmaması için genel yazdırma sürücüleri kullanıyoruz.
$PrinterType = New-Object system.Windows.Forms.ComboBox
$PrinterType.text = ""
$PrinterType.width = 170
$printerType.autosize = $true
# Add the items in the dropdown list
@('Canon','Hp') | ForEach-Object {[void] $PrinterType.Items.Add($_)}
# Select the default value
$PrinterType.SelectedIndex = 0
$PrinterType.location = New-Object System.Drawing.Point(20,210)
$PrinterType.Font = 'Microsoft Sans Serif,10'Yukarıdaki kod oldukça açık sanırım, açılan kutuyu oluşturup tek satırlık foreach döngüsüne sahip öğeleri listeye ekliyoruz. Yine konumu da tanımlıyoruz ve eleman için minimum bir genişlik belirledim.
Dizini seçerek açılır listeniz için varsayılan bir değer ayarlayabilirsiniz. Öğenin değişkenini $LocalPrinterForm.controls.AddRange'ye eklediğinizden emin olun, aksi halde görüntülenmez.
Düğme ekleme
Ayrıca formumuza bazı düğmeler ekleyeceğiz. Bir düğmenin (
Tamam, İptal, İptal, Yeniden Dene, Yoksay, Evet veya Hayır) gibi standart bir eylemi olabilir veya ona özel bir işlev atayabilirsiniz.
Ekleyeceğimiz butonlar İptal ve Yazıcı Ekle'dir. İptal yalnızca formu kapatır ve başka hiçbir şey yapmaz; AddPrinter ise yazıcıyı eklemek için mantığımızı çalıştırır. Aşağıdaki koda sahip butonları ekleyin, yine butonların değişkenlerini $LocalPrinterForm.controls.AddRange'e eklediğinizden emin olun.
$AddPrinterBtn = New-Object system.Windows.Forms.Button
$AddPrinterBtn.BackColor = "#a4ba67"
$AddPrinterBtn.text = "Add Printer"
$AddPrinterBtn.width = 90
$AddPrinterBtn.height = 30
$AddPrinterBtn.location = New-Object System.Drawing.Point(370,250)
$AddPrinterBtn.Font = 'Microsoft Sans Serif,10'
$AddPrinterBtn.ForeColor = "#ffffff"
$cancelBtn = New-Object system.Windows.Forms.Button
$cancelBtn.BackColor = "#ffffff"
$cancelBtn.text = "Cancel"
$cancelBtn.width = 90
$cancelBtn.height = 30
$cancelBtn.location = New-Object System.Drawing.Point(260,250)
$cancelBtn.Font = 'Microsoft Sans Serif,10'
$cancelBtn.ForeColor = "#000"
$cancelBtn.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$LocalPrinterForm.CancelButton = $cancelBtn
$LocalPrinterForm.Controls.Add($cancelBtn)Artık diğer web sitelerindeki birçok örnekte, [void]$form.ShowDialog() kullanılarak iletişim kutusunun sonuçları atılıyor. Ancak, kullanıcının nasıl kapandığını anlatmak için iletişim kutusunun dönüş değeri kullanılmalıdır. form.
Bu yüzden ShowDialog cmd'sini değiştireceğiz.
$result = $LocalPrinterForm.ShowDialog()Bu şekilde kullanıcının İptal'e veya formdaki herhangi bir varsayılan düğmeye basıp basmadığını kontrol edebiliriz.
if ($result -eq [System.Windows.Forms.DialogResult]::Cancel)
{
write-output 'User pressed cancel'
}Bir düğmeye özel işlev ekleme
Kullanıcı Yazıcı Ekle'yi tıkladığında özel bir komut dosyası çalıştırılmalıdır. Mantığımızla bir fonksiyon oluşturup aşağıdaki cmd ile bu fonksiyonu butona atayabiliriz.
$AddPrinterBtn.Add_Click({ AddPrinter })Ve bizim fonksiyonumuz
function AddPrinter {
# ADDING PRINTER LOGIC GOES HERE
}Sonuç
Tüm öğeleri ekledikten ve bazı ekstra etiketler ekledikten sonra son PowerShell GUI formumuz şöyle görünür:
Artık bir yazıcının eklenmesi için betiğimizi bitirmemiz yeterli.
Mantık ekleme
Formumuz hazır olduğundan mantığı ekleyerek başlayabiliriz. Komut dosyanızın yürütülmesi sırasında metni değiştirmek, alanları göstermek veya kaldırmak ya da belirli bir eylem gerçekleştirmek isteyebilirsiniz. İlk önce PowerShell betiğimizin ana hatlarını çizerek başlayalım.
#------------[Initialisations]------------
# Init PowerShell Gui
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
#---------------[Form]-------------------
# Our form goes here
[System.Windows.Forms.Application]::EnableVisualStyles()
$LocalPrinterForm = New-Object system.Windows.Forms.Form
$LocalPrinterForm.ClientSize = '480,300'
$LocalPrinterForm.text = "LazyAdmin - PowerShell GUI Example"
$LocalPrinterForm.BackColor = "#ffffff"
$LocalPrinterForm.TopMost = $false
$Icon = New-Object system.drawing.icon ("./form.ico")
$LocalPrinterForm.Icon = $Icon
# THE REST OF THE FORM
$LocalPrinterForm.controls.AddRange(@( "<ALL FORM ELEMENTS>" ))
#------------[Functions]------------
function AddPrinter {
# Function that is triggered with the add printer button
}
#------------[Script]------------
$AddPrinterBtn.Add_Click({ AddPrinter })
# REST OF YOUR SCRIPT
#------------[Show form]------------
# Show the form
$result = $LocalPrinterForm.ShowDialog()
# Catch any output of the form
if ($result -eq [System.Windows.Forms.DialogResult]::Cancel)
{
write-output 'User pressed cancel'
}İşlevler veya komut dosyası bölümünüzde kullanıcıya geri bildirimde bulunmak veya giriş alanlarındaki verileri kullanmak isteyebilirsiniz.
PowerShell GUI Öğelerini okuma ve değiştirme
Metin kutusundan veri okumak oldukça basittir. Örneğimizde kullanıcıların girdiği adı kullanarak yazıcı adının zaten var olup olmadığını kontrol etmek istiyoruz. Eğer isim mevcutsa bir hata göstermek istiyoruz.
if (Get-Printer -Name $printerName.text) {
$PrinterStatus.ForeColor = "#D0021B"
$PrinterStatus.Text = 'Printer name already exists.'
}Yukarıdaki örnekte verilen yazıcı adını kontrol ediyoruz, eğer varsa “PrinterStatus” etiketinin yazı tipi rengini değiştirerek kullanıcılara bir mesaj gösterecek şekilde etiket metnini okuyoruz ve değiştiriyoruz.
Formu veya girişi yenilemenize gerek yoktur; metni ilerledikçe değiştirebilirsiniz.
Alanları gösterme ve gizleme
Form yüklenmeden önce beklenen ağ adresinde yazıcı olup olmadığını kontrol ediyorum. Aksi takdirde kullanıcının devam etmesine gerek yoktur. Yani form elemanlarını ilklendirdiğimde bazı elemanları gizledim.
Bir bağlantımız varsa, o zaman örneğin öğeleri gösteririm veya düğmelerin etiketini değiştiririm. PowerShell GUI'deki öğeleri gizleme ve gösterme işlemi aşağıdaki kodla yapılabilir:
$PrinterNameLabel.Visible = $false # or $true of course ?Çevrimiçi PowerShell GUI Düzenleyicisi PoshGUI
Yalnızca komut satırından daha büyük veya karmaşık bir form oluşturmak biraz zorlayıcı olabilir. Tüm öğeleri doğru yere yerleştirmeniz, gerekli tüm kodu oluşturmanız gerekecek. Neyse ki çevrimiçi bir PowerShell GUI editörü PoshGUI var.
Bu, ilk form düzeninizi oluşturmak için harika bir araçtır. PS1 dosyasını indirebilir ve favori düzenleyicinizde formunuz üzerinde çalışmaya devam edebilirsiniz.
Çözüm
Bu makalenin ilk PowerShell formunuzu oluşturmaya başlamanıza yardımcı olacağını umuyorum. PowerShell aslında form oluşturmak için tasarlanmasa da, bir komut dosyasını kullanıcılarınız veya meslektaşlarınız için daha kullanışlı hale getirmenin harika bir yolu olabilir.
PowerShell veya Office 365 hakkındaki en son makaleleri posta kutunuza almak için bültene abone olun.
Kodun tamamı aşağıdaki gibi görünür:
#---------------------------------------------------------[Initialisations]--------------------------------------------------------
# Init PowerShell Gui
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
#---------------------------------------------------------[Form]--------------------------------------------------------
[System.Windows.Forms.Application]::EnableVisualStyles()
$LocalPrinterForm = New-Object system.Windows.Forms.Form
$LocalPrinterForm.ClientSize = '480,300'
$LocalPrinterForm.text = "Printers"
$LocalPrinterForm.BackColor = "#ffffff"
$LocalPrinterForm.TopMost = $false
$Icon = New-Object system.drawing.icon ("//thunnissen.local/netlogon/printer.ico")
$LocalPrinterForm.Icon = $Icon
$Titel = New-Object system.Windows.Forms.Label
$Titel.text = "Add new printer"
$Titel.AutoSize = $true
$Titel.width = 25
$Titel.height = 10
$Titel.location = New-Object System.Drawing.Point(20,20)
$Titel.Font = 'Microsoft Sans Serif,13'
$Description = New-Object system.Windows.Forms.Label
$Description.text = "To add a printer, make sure you are connected to the same network as the printer.."
$Description.AutoSize = $false
$Description.width = 450
$Description.height = 50
$Description.location = New-Object System.Drawing.Point(20,50)
$Description.Font = 'Microsoft Sans Serif,10'
$PrinterStatus = New-Object system.Windows.Forms.Label
$PrinterStatus.text = "Status:"
$PrinterStatus.AutoSize = $true
$PrinterStatus.width = 25
$PrinterStatus.height = 10
$PrinterStatus.location = New-Object System.Drawing.Point(20,115)
$PrinterStatus.Font = 'Microsoft Sans Serif,10,style=Bold'
$PrinterFound = New-Object system.Windows.Forms.Label
$PrinterFound.text = "Searching for printer..."
$PrinterFound.AutoSize = $true
$PrinterFound.width = 25
$PrinterFound.height = 10
$PrinterFound.location = New-Object System.Drawing.Point(100,115)
$PrinterFound.Font = 'Microsoft Sans Serif,10'
$PrinterDetails = New-Object system.Windows.Forms.Label
$PrinterDetails.text = "Printer details"
$PrinterDetails.AutoSize = $true
$PrinterDetails.width = 25
$PrinterDetails.height = 10
$PrinterDetails.location = New-Object System.Drawing.Point(20,150)
$PrinterDetails.Font = 'Microsoft Sans Serif,12'
$PrinterDetails.Visible = $false
$PrinterNameLabel = New-Object system.Windows.Forms.Label
$PrinterNameLabel.text = "Name:"
$PrinterNameLabel.AutoSize = $true
$PrinterNameLabel.width = 25
$PrinterNameLabel.height = 20
$PrinterNameLabel.location = New-Object System.Drawing.Point(20,180)
$PrinterNameLabel.Font = 'Microsoft Sans Serif,10,style=Bold'
$PrinterNameLabel.Visible = $false
$PrinterName = New-Object system.Windows.Forms.TextBox
$PrinterName.multiline = $false
$PrinterName.width = 314
$PrinterName.height = 20
$PrinterName.location = New-Object System.Drawing.Point(100,180)
$PrinterName.Font = 'Microsoft Sans Serif,10'
$PrinterName.Visible = $false
$PrinterTypeLabel = New-Object system.Windows.Forms.Label
$PrinterTypeLabel.text = "Brand:"
$PrinterTypeLabel.AutoSize = $true
$PrinterTypeLabel.width = 25
$PrinterTypeLabel.height = 20
$PrinterTypeLabel.location = New-Object System.Drawing.Point(20,210)
$PrinterTypeLabel.Font = 'Microsoft Sans Serif,10,style=Bold'
$PrinterTypeLabel.Visible = $false
$PrinterType = New-Object system.Windows.Forms.ComboBox
$PrinterType.text = ""
$PrinterType.width = 170
$PrinterType.height = 20
@('Canon','Hp') | ForEach-Object {[void] $PrinterType.Items.Add($_)}
$PrinterType.SelectedIndex = 0
$PrinterType.location = New-Object System.Drawing.Point(100,210)
$PrinterType.Font = 'Microsoft Sans Serif,10'
$PrinterType.Visible = $false
$AddPrinterBtn = New-Object system.Windows.Forms.Button
$AddPrinterBtn.BackColor = "#ff7b00"
$AddPrinterBtn.text = "Add"
$AddPrinterBtn.width = 90
$AddPrinterBtn.height = 30
$AddPrinterBtn.location = New-Object System.Drawing.Point(370,250)
$AddPrinterBtn.Font = 'Microsoft Sans Serif,10'
$AddPrinterBtn.ForeColor = "#ffffff"
$AddPrinterBtn.Visible = $false
$cancelBtn = New-Object system.Windows.Forms.Button
$cancelBtn.BackColor = "#ffffff"
$cancelBtn.text = "Cancel"
$cancelBtn.width = 90
$cancelBtn.height = 30
$cancelBtn.location = New-Object System.Drawing.Point(260,250)
$cancelBtn.Font = 'Microsoft Sans Serif,10'
$cancelBtn.ForeColor = "#000"
$cancelBtn.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$LocalPrinterForm.CancelButton = $cancelBtn
$LocalPrinterForm.Controls.Add($cancelBtn)
$LocalPrinterForm.controls.AddRange(@($Titel,$Description,$PrinterStatus,$PrinterFound,$PrinterName,$PrinterNameLabel,$PrinterType,$AddPrinterBtn,$cancelBtn,$PrinterTypeLabel,$PrinterDetails))
#-----------------------------------------------------------[Functions]------------------------------------------------------------
function AddPrinter {
$PrinterFound.ForeColor = "#000000"
$PrinterFound.Text = 'Adding printer...'
# Check printer port
$portName = "TCPPort:"+$printerIp
$portExists = Get-Printerport -Name $portname -ErrorAction SilentlyContinue
# Create port if it not exists
if (-not $portExists) {
$PrinterFound.Text = 'Creating printer port...'
Add-PrinterPort -name $portName -PrinterHostAddress $printerIp
}
# Select the correct driver
if ($PrinterType.SelectedItem -eq 'Canon') {
$printerDriverName = "Canon Generic Plus PCL6"
}else{
$printerDriverName = "HP LaserJet M227-M231 PCL-6"
}
# Check if printer driver exists
$printDriverExists = Get-PrinterDriver -name $printerDriverName -ErrorAction SilentlyContinue
# Install printer or printer driver and printer
if ($printDriverExists) {
$PrinterFound.Text = 'Installing printer...'
Add-Printer -Name $printerName.text -PortName $portName -DriverName $printerDriverName
}else{
$PrinterFound.Text = 'Installing printer driver...'
Add-PrinterDriver -name $printerDriverName
$PrinterFound.Text = 'Installing printer...'
Add-Printer -Name $printerName.text -PortName $portName -DriverName $printerDriverName
}
if (Get-Printer -Name $printerName.text) {
$PrinterFound.ForeColor = "#7ed321"
$PrinterFound.Text = 'The printer is installed'
}
else {
$PrinterFound.ForeColor = "#D0021B"
$PrinterFound.Text = 'Installation failed'
}
$PrinterNameLabel.Visible = $false
$PrinterName.Visible = $false
$PrinterType.Visible = $false
$AddPrinterBtn.Visible = $false
$PrinterDetails.Visible = $false
$PrinterTypeLabel.Visible = $false
$cancelBtn.text = "Close"
}
#---------------------------------------------------------[Script]--------------------------------------------------------
# Get printers IP Address
$clientIP = (
Get-NetIPConfiguration |
Where-Object {
$_.IPv4DefaultGateway -ne $null -and
$_.NetAdapter.Status -ne "Disconnected"
}
).IPv4Address.IPAddress
$networkAddress = $clientIP.Split('.')
$networkAddress = $networkAddress[0]+"."+$networkAddress[1]+"."+$networkAddress[2]
# Check if printer is online
$printerIp = $networkAddress + ".31"
$testConnection = Test-Connection $printerIp -count 1 -Quiet
If ($testConnection) {
$PrinterFound.text = "Printer found"
$PrinterFound.ForeColor = "#7ed321"
$PrinterNameLabel.Visible = $true
$PrinterName.Visible = $true
$PrinterType.Visible = $true
$AddPrinterBtn.Visible = $true
$PrinterDetails.Visible = $true
$PrinterTypeLabel.Visible = $true
}else{
$PrinterFound.text = "No printers found"
$PrinterFound.ForeColor = "#D0021B"
$cancelBtn.text = "Sluiten"
}
$AddPrinterBtn.Add_Click({ AddPrinter })
[void]$LocalPrinterForm.ShowDialog()Ayrıca aşağıdaki makalelere de göz atabilirsiniz:
- PowerShell ile yazıcılar ve yazıcı bağlantı noktaları ekleme
- PowerShell ile ana klasörleri OneDrive'a geçirme
- Microsoft Flow'u kullanmaya başlama



