اشتراکها
از قبل در لینوکس وجود داشت در ورژن 17.06 برای ویندوز نیز موجود میشود.
Secrets are a first-class citizen in Docker. They're for storing sensitive application data, like API keys and connection strings. Secrets have been in Docker on Linux for a while, and with Docker version 17.06 they're coming to Windows.
اشتراکها
راهنمای نصب TFS 2017
مفهوم «ابزارها» و یا «project tools» از نگارش اول NET Core. به همراه آن است؛ مانند تنظیم زیر در فایل csproj برنامهها:
که سبب فعالسازی ابزار dotnet ef میشود و توسط آن میتوان دستورات dotnet ef database update و یا dotnet ef migrations add را بر روی پروژهی جاری اجرا کرد. در این حالت برنامه dotnet.exe، هاست اجرایی این ابزارهای محلی و مختص به یک پروژه است.
این ایده نیز از npm و ابزارهای محلی و مختص به یک پروژهی آن گرفته شدهاست. اما npm امکان نصب این ابزارها را به صورت سراسری نیز دارد که امکان وجود linters ، test runners و یا development web servers را میسر کردهاست و در این حالت نیازی نیست یک چنین ابزارهایی را به ازای هر پروژه نیز یکبار نصب کرد.
معرفی ابزارهای سراسری در NET Core 2.1.
اگر SDK جدید NET Core 2.1 را نصب کرده باشید، پس از Build یک پروژهی مبتنی بر NET Core 2.0. (که توسط فایل global.json، شماره SDK آن محدود و مقید نشدهاست) یک چنین پیامهای اخطاری را مشاهده خواهید کرد:
یکی از ویژگیهای جدید NET Core 2.1 معرفی global tools یا ابزارهای سراسری آن است. هدف از آن، تهیه برنامههای کنسول مبتنی بر NET Core. است که توسط NuGet توزیع و به روز رسانی میشوند. توسعه دهندگان جاوا اسکریپت با یک چنین مفهومی تحت عنوان ابزارهای سراسری NPM آشنا هستند (NPM global tools)؛ همان سوئیچ g- که یک ابزار جاوا اسکریپتی را به صورت سراسری نصب میکند؛ مانند کامپایلر TypeScript.
پیامهای اخطار فوق نیز به این معنا هستند که دیگر نیازی نیست تا برای اجرای دستور dotnet watch run، حتما ابزار پروژهی Microsoft.DotNet.Watcher.Tools را به صورت دستی به تمام فایلهای csproj خود اضافه کنید. ابزار Watcher و یا EntityFrameworkCore.Tools اکنون جزو ابزارهای سراسری NET Core 2.1. هستند و بدون نیازی به افزودن ارجاع خاصی به آنها، هم اکنون در تمام پروژههای NET Core. شما قابل دسترسی و استفاده هستند. بنابراین ارجاعات مستقیم به آنها را حذف کنید؛ چون غیرضروری میباشند.
روش نصب ابزارهای سراسری در NET Core.
روش نصب ابزارهای سراسری NET Core. به صورت زیر است:
با این دستور، برنامهی فرضی example از نیوگت دریافت شده و ابتدا در یکی از دو پوشهی زیر، فایل فشرده شدهی آن باز خواهد شد:
و سپس در ویندوز، در مسیر زیر قرار خواهد گرفت (محل نصب نهایی):
این مسیر در لینوکس به صورت زیر است:
در حال حاضر برای عزل این برنامهها باید به یکی از این مسیرها مراجعه و آنها را دستی حذف کرد (در هر دو مسیر toolspkgs و tools باید حذف شوند).
یک نمونه از این ابزارها را که dotnet-dev-certs نام دارد، پس از نصب SDK جدید، در مکانهای یاد شده، خواهید یافت. کار این ابزار سراسری، تولید یک self signed certificate مخصوص برنامههای ASP.NET Core 2.1 است که پیشتر در مطلب «اجبار به استفادهی از HTTPS در حین توسعهی برنامههای ASP.NET Core 2.1» آنرا بررسی کردیم.
نکته 1: بر اساس تصویر فوق، در خط فرمان، دستور dotnet-dev-certs را صادر کنید. اگر پیام یافت نشدن این دستور یا ابزار را مشاهده کردید، به معنای این است که مسیر نصب آنها به PATH سیستم اضافه نشدهاست. با استفاده از دستورات ذیل میتوانید این مسیر را به PATH سیستم اضافه کنید:
نکته 2: اگر به این مسیرها دقت کنید، این ابزارها صرفا برای کاربر جاری سیستم نصب میشوند و مختص به او هستند؛ به عبارتی user-specific هستند و نه machine global.
روش ایجاد ابزارهای سراسری NET Core.
همانطور که عنوان شد، ابزارهای سراسری NET Core. در اصل برنامههای کنسول آن هستند. به همین جهت پس از نصب SDK جدید، در یک پوشهی جدید، دستور dotnet new console را اجرا کنید تا یک برنامهی کنسول جدید مطابق آن ایجاد شود. سپس فایل csproj آنرا به صورت زیر ویرایش کنید:
در اینجا دو خاصیت IsPackable و PackAsTool جدید بوده و مختص به ابزارهای سراسری NET Core. هستند. تنظیم همین دو خاصیت برای تبدیل یک برنامهی کنسول معمولی به ابزار سراسری کافی است.
پس از آن برای تهیهی یک بستهی نیوگت از آن، دستور زیر را اجرا کنید:
پس از ارسال فایل nupkg حاصل به سایت نیوگت، کاربران آن میتوانند توسط دستور زیر آنرا نصب کنند:
<ItemGroup> <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" /> </ItemGroup>
این ایده نیز از npm و ابزارهای محلی و مختص به یک پروژهی آن گرفته شدهاست. اما npm امکان نصب این ابزارها را به صورت سراسری نیز دارد که امکان وجود linters ، test runners و یا development web servers را میسر کردهاست و در این حالت نیازی نیست یک چنین ابزارهایی را به ازای هر پروژه نیز یکبار نصب کرد.
معرفی ابزارهای سراسری در NET Core 2.1.
اگر SDK جدید NET Core 2.1 را نصب کرده باشید، پس از Build یک پروژهی مبتنی بر NET Core 2.0. (که توسط فایل global.json، شماره SDK آن محدود و مقید نشدهاست) یک چنین پیامهای اخطاری را مشاهده خواهید کرد:
warning : Using DotNetCliToolReference to reference 'Microsoft.EntityFrameworkCore.Tools.DotNet' is obsolete and can be removed from this project. This tool is bundled by default in the .NET Core SDK. warning : Using DotNetCliToolReference to reference 'Microsoft.DotNet.Watcher.Tools' is obsolete and can be removed from this project. This tool is bundled by default in the .NET Core SDK.
پیامهای اخطار فوق نیز به این معنا هستند که دیگر نیازی نیست تا برای اجرای دستور dotnet watch run، حتما ابزار پروژهی Microsoft.DotNet.Watcher.Tools را به صورت دستی به تمام فایلهای csproj خود اضافه کنید. ابزار Watcher و یا EntityFrameworkCore.Tools اکنون جزو ابزارهای سراسری NET Core 2.1. هستند و بدون نیازی به افزودن ارجاع خاصی به آنها، هم اکنون در تمام پروژههای NET Core. شما قابل دسترسی و استفاده هستند. بنابراین ارجاعات مستقیم به آنها را حذف کنید؛ چون غیرضروری میباشند.
روش نصب ابزارهای سراسری در NET Core.
روش نصب ابزارهای سراسری NET Core. به صورت زیر است:
dotnet tool install -g example
%USERPROFILE%\.dotnet\toolspkgs (Windows) $HOME/.dotnet/toolspkgs (macOS/Linux)
%USERPROFILE%\.dotnet\tools
~/.dotnet/tools
در حال حاضر برای عزل این برنامهها باید به یکی از این مسیرها مراجعه و آنها را دستی حذف کرد (در هر دو مسیر toolspkgs و tools باید حذف شوند).
یک نمونه از این ابزارها را که dotnet-dev-certs نام دارد، پس از نصب SDK جدید، در مکانهای یاد شده، خواهید یافت. کار این ابزار سراسری، تولید یک self signed certificate مخصوص برنامههای ASP.NET Core 2.1 است که پیشتر در مطلب «اجبار به استفادهی از HTTPS در حین توسعهی برنامههای ASP.NET Core 2.1» آنرا بررسی کردیم.
نکته 1: بر اساس تصویر فوق، در خط فرمان، دستور dotnet-dev-certs را صادر کنید. اگر پیام یافت نشدن این دستور یا ابزار را مشاهده کردید، به معنای این است که مسیر نصب آنها به PATH سیستم اضافه نشدهاست. با استفاده از دستورات ذیل میتوانید این مسیر را به PATH سیستم اضافه کنید:
Windows PowerShell: setx PATH "$env:PATH;$env:USERPROFILE/.dotnet/tools" Linux/macOS: echo "export PATH=\"\$PATH:\$HOME/.dotnet/tools\"" >> ~/.bash_profile
نکته 2: اگر به این مسیرها دقت کنید، این ابزارها صرفا برای کاربر جاری سیستم نصب میشوند و مختص به او هستند؛ به عبارتی user-specific هستند و نه machine global.
روش ایجاد ابزارهای سراسری NET Core.
همانطور که عنوان شد، ابزارهای سراسری NET Core. در اصل برنامههای کنسول آن هستند. به همین جهت پس از نصب SDK جدید، در یک پوشهی جدید، دستور dotnet new console را اجرا کنید تا یک برنامهی کنسول جدید مطابق آن ایجاد شود. سپس فایل csproj آنرا به صورت زیر ویرایش کنید:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <IsPackable>true</IsPackable> <PackAsTool>true</PackAsTool> <TargetFramework>netcoreapp2.1</TargetFramework> </PropertyGroup> </Project>
پس از آن برای تهیهی یک بستهی نیوگت از آن، دستور زیر را اجرا کنید:
dotnet pack -c Release
dotnet tool install -g package-name
توسط ماژولها میتوانیم یک مجموعه از دستورات را گروهبندی کنیم و تحت عنوان یک پکیج ارائه دهیم که برای دیگران نیز قابل استفاده باشند. برای ایجاد یک ماژول کافی است اسکریپتهای خود را درون یک فایل با پسوند psm1 قرار دهیم؛ به این فایل اصطلاحاً root module گفته میشود. در واقع میتوان گفت ماژولها یک روش مناسب برای به اشتراکگذاری اسکریپتها میباشند. تا اینجا با کمک پروفایلها توانستیم امکان استفاده مجدد از توابع و اسکریپتها را داشته باشیم؛ ماژولها نیز یک روش دیگر برای بارگذاری اسکریپتها درون شل هستند. زمانیکه شل را باز میکنیم PowerShell به صورت خودکار یکسری مسیر را برای بارگذاری ماژولها اسکن میکند. توسط متغیر env:PSModulePath$ میتوانیم لیست این مسیرها را ببینیم:
همانطور که عنوان شد برای ایجاد یک ماژول کافی است اسکریپتهای خود را داخل یک فایل با پسوند psm1 ذخیره کنیم. به عنوان مثال میتوانیم تابع Get-PingReply را درون یک فایل با نام PingModule.psm1 ذخیره و سپس توسط دستور Import-Module ماژول را ایمپورت کنیم:
سپس توسط دستور Get-Module PingModule میتوانیم جزئیات ماژول ایمپورت شده را مشاهده نمائیم:
به صورت پیشفرض تمام توابع درون اسکریپت export خواهند شد. اگر ExportedCommands خالی باشد به این معنا است که ماژول به درستی ایمپورت نشدهاست. به عنوان مثال اگر سعی کنید فایل قبل را با پسوند ps1 به عنوان ماژول ایمپورت کنید. خطایی هنگام ایمپورت کردن مشاهده نخواهید کرد و قسمت ExportedCommands خالی خواهد بود. در اینحالت نیز امکان استفاده از تابع درون اسکریپت را خواهیم داشت؛ اما هیچ تضمینی نیست که به صورت یک ماژول به درستی عمل کند. بنابراین بهتر است ماژولهایی که ایجاد میکنیم حتماً پسوند psm1 داشته باشند.
ممکن است بخواهیم یکسری توابع را به صورت private تعریف کنیم و فقط تعداد محدودی از توابع به صورت public باشند. در این حالت میتوانیم درون فایل psm1 با کمک دستور Export-ModuleMember اینکار را انجام دهیم:
تنها پراپرتی موردنیاز برای ایجاد module manifest پراپرتی Path میباشد. این پراپرتی به فایلی که متادیتا قرار است درون آن ایجاد شود اشاره دارد. همانطور که مشاهده میکنید یکسری پراپرتی دیگر نیز اضافه کردهایم و توسط splatted hash table (با کمک @) به دستور New-ModuleManifest ارسال کردهایم. به این معنا که کلیدها و مقادیر درون hash table به جای اینکه یکجا به عنوان یک آبجکت به دستور موردنظر ارسال شوند، به صورت جدا پاس داده شدهاند. اما اگر از $ استفاده میکردیم:
با خطای زیر مواجه میشدیم:
در نهایت فایل manifest در مسیر تعیین شده ایجاد خواهد شد:
هر ماژول باید یک آیدی منحصر به فرد داشته باشد که به صورت Guid توسط یک پراپرتی با همین نام تعیین میشود. برای هر پراپرتی درون این فایل توضیحی به صورت کامنت نوشته شده است؛ اما برای دیدن جزئیات کامل میتوانید به اینجا مراجعه نمائید. در اینجا RootModule به PingModule.psm1 تنظیم شده است. تنظیم این پراپرتی نحوه نمایش module type را در خروجی Get-Module مشخص میکند. این مقدار اگر به فایل ماژول (psm1) اشاره کند، نوع ماژول script در نظر گرفته میشود، اگر به یک DLL اشاره کند به binary و در نهایت اگر به یک فایلی با پسوند دیگری اشاره کند manifest در نظر گرفته میشود. همچنین درون فایل فوق یکسری پراپرتی مانند CmdletsToExport, VariablesToExport, AliasesToExport به صورت خودکار تنظیم شدهاند. در نهایت برای تست صحت فایل میتوانیم از دستور Test-ModuleManifest استفاده کنیم:
در کد فوق میتوانید مقدار متغیر RepoPath را به محل مدنظر روی سیستمتان تنظیم کنید. ساختار ماژولی که میخواهیم پابلیش کنیم نیز اینچنین خواهد بود:
در ادامه برای پابلیش ماژول فوق درون ProjectRoot دستور Publish-Module را اینگونه اجرا خواهیم کرد:
خروجی دستور فوق یک فایل با پسوند nupkg در مسیر مخزنی است که معرفی کردیم. همچنین با کمک دستور Find-Module میتوانیم ماژول موردنظر را لیست کنیم:
برای نصب ماژول روی یک سیستم دیگر نیز ابتدا باید مطمئن شوید که سیستم مقصد، مخزن لوکال را تعریف کرده باشد و در نهایت توسط دستور Install-Module میتوانیم ماژول موردنظر را نصب کنیم:
همچنین امکان پابلیش کردن ورژنهای متفاوت را نیز خواهیم داشت:
برای پابلیش کردن هر کدام از ماژولهای فوق باید به ازای هر کدام یکبار دستور Publish-Module را اجرا کنیم:
اکنون حین نصب ماژول میتوانیم ورژن را نیز تعیین کنیم؛ در غیراینصورت آخرین ورژن یعنی 1.0.1 نصب خواهد شد:
در اینحالت باید اسکریپتها و فایلهای موردنیاز را توسط dot sourcing درون فایل ماژول بارگذاری کنیم:
بنابراین ساختار پروژه را اینگونه ایجاد خواهیم کرد:
برای استفاده از پکیج ذکر شده نیاز خواهد بود که Dllهای موردنیاز را نیز به عنوان وابستگی به پروژه اضافه کنیم (محتویات پوشه dependencies) سپس درون فایل ماژول (SignPdf.psm1) همانطور که عنوان شد میبایست اسکریپتها درون پوشه Public را بارگذاری کنیم و همچنین درون تابعی که قرار است Export شود را نیز تعیین کردهایم (Set-PDFSingature)
در ادامه درون فایل Set-PDFSignature پیادهسازی را انجام خواهیم داد:
روال قرار دادن یک امضاء بر روی یک فایل PDF قبلاً در سایت توضیح داده شده است. کدهای فوق در واقع معادل PowerShell همان کدهای موجود در سایت هستند و نکته خاصی ندارند. در نهایت میتوانیم ماژول تهیه شده را روی مخزن موردنظر پابلیش کنیم:
برای نصب ماژول میتوانیم از دستور Install-Module استفاده کنیم:
در نهایت برای استفاده از ماژول ایجاد شده میتوانیم اینگونه عمل کنیم:
خروجی نیز فایل امضاء شده خواهد بود:
PS /> $env:PSModulePath -Split ":" /Users/sirwanafifi/.local/share/powershell/Modules /usr/local/share/powershell/Modules /usr/local/microsoft/powershell/7/Modules
PS /> Import-Module ./PingModule.psm1
PS /> Get-Module PingModule ModuleType Version PreRelease Name ExportedCommands ---------- ------- ---------- ---- ---------------- Script 0.0 PingModule Get-PingReply
PS /> Import-Module ./PingModule.ps1 PS /> Get-Module PingModule ModuleType Version PreRelease Name ExportedCommands ---------- ------- ---------- ---- ---------------- Script 0.0 PingModule
Function Get-PingReply { // as before } Function Get-PrivateFunction { Write-Debug 'This is a private function' } Export-ModuleMember -Function @( 'Get-PingReply' )
اضافه کردن متادیتا به ماژولها
برای هر ماژول میتوانیم با کمک module manifest یکسری متادیتا به ماژول اضافه کنیم. این متادیتا درون یک فایل با پسوند psd1 که محتویات آن در واقع یک Hashtable است ذخیره میشود. برای ایجاد فایل manifest میتوانیم از دستور New-ModuleManifest استفاده کنیم. به عنوان مثال برای ایجاد فایل manifest برای ماژول PingModule.psm1 اینگونه عمل خواهیم کرد:
$moduleSettings = @{ Path = './PingModule.psd1' Description = 'A module to ping a remote system' RootModule = 'PingModule.psm1' ModuleVersion = '1.0.0' FunctionsToExport = @( 'Get-PingReply' ) PowerShellVersion = '5.1' CompatiblePSEditions = @( 'Core' 'Desktop' ) } New-ModuleManifest @moduleSettings
$moduleSettings = @{ Author = 'John Doe' Description = 'This is a sample module' } New-ModuleManifest $moduleSettings
New-ModuleManifest : A parameter cannot be found that matches parameter name 'Author'.
# # Module manifest for module 'PingModule' # # Generated by: sirwanafifi # # Generated on: 01/01/2023 # @{ # Script module or binary module file associated with this manifest. RootModule = './PingModule.psm1' # Version number of this module. ModuleVersion = '1.0.0' # Supported PSEditions CompatiblePSEditions = 'Core', 'Desktop' # ID used to uniquely identify this module GUID = '3f8561fc-c004-4c8e-b2fc-4a4191504131' # Author of this module Author = 'sirwanafifi' # Company or vendor of this module CompanyName = 'Unknown' # Copyright statement for this module Copyright = '(c) sirwanafifi. All rights reserved.' # Description of the functionality provided by this module Description = 'A module to ping a remote system' # Minimum version of the PowerShell engine required by this module PowerShellVersion = '5.1' # Name of the PowerShell host required by this module # PowerShellHostName = '' # Minimum version of the PowerShell host required by this module # PowerShellHostVersion = '' # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. # DotNetFrameworkVersion = '' # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. # ClrVersion = '' # Processor architecture (None, X86, Amd64) required by this module # ProcessorArchitecture = '' # Modules that must be imported into the global environment prior to importing this module # RequiredModules = @() # Assemblies that must be loaded prior to importing this module # RequiredAssemblies = @() # Script files (.ps1) that are run in the caller's environment prior to importing this module. # ScriptsToProcess = @() # Type files (.ps1xml) to be loaded when importing this module # TypesToProcess = @() # Format files (.ps1xml) to be loaded when importing this module # FormatsToProcess = @() # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess # NestedModules = @() # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. FunctionsToExport = 'Get-PingReply' # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. CmdletsToExport = '*' # Variables to export from this module VariablesToExport = '*' # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. AliasesToExport = '*' # DSC resources to export from this module # DscResourcesToExport = @() # List of all modules packaged with this module # ModuleList = @() # List of all files packaged with this module # FileList = @() # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. PrivateData = @{ PSData = @{ # Tags applied to this module. These help with module discovery in online galleries. # Tags = @() # A URL to the license for this module. # LicenseUri = '' # A URL to the main website for this project. # ProjectUri = '' # A URL to an icon representing this module. # IconUri = '' # ReleaseNotes of this module # ReleaseNotes = '' # Prerelease string of this module # Prerelease = '' # Flag to indicate whether the module requires explicit user acceptance for install/update/save # RequireLicenseAcceptance = $false # External dependent modules of this module # ExternalModuleDependencies = @() } # End of PSData hashtable } # End of PrivateData hashtable # HelpInfo URI of this module # HelpInfoURI = '' # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. # DefaultCommandPrefix = '' }
PS /> Test-ModuleManifest ./PingModule.psd1 ModuleType Version PreRelease Name ExportedCommands ---------- ------- ---------- ---- ---------------- Script 1.0.0 PingModule Get-PingReply
پابلیش ماژول
در نهایت توسط Publish-Module میتوانیم ماژول موردنظرمان را درون یک مخزن PowerShell پابلیش کنیم. رایجترین مخزن برای انتشار پکیجهای PowerShell یک فید نیوگت (مانند PowerShell Gallery) است. همچنین میتوانیم یک مخزن لوکال نیز برای پابلیش پکیجها نیز ایجاد کنیم و خروجی نهایی را به صورت یک فایل با پسوند nupkg با دیگران به اشتراک بگذاریم. برای اینکار ابتدا نیاز است یک مخزن لوکال را به PowerShell معرفی کنیم:
PS /> Register-PSRepository -Name 'PSLocal' ` >> -SourceLocation "$(Resolve-Path $RepoPath)" ` >> -PublishLocation "$(Resolve-Path $RepoPath)" ` >> -InstallationPolicy 'Trusted'
ProjectRoot | -- PingModule | -- PingModule.psd1 | -- PingModule.psm1
PS /> Publish-Module -Path ./PingModule/ -Repository PSLocal
PS /> Find-Module -Name PingModule -Repository PSLocal Version Name Repository Description ------- ---- ---------- ----------- 0.0.1 PingModule PSLocal Get-PingReply is a.
PS /> Install-Module -Name PingModule -Repository PSLocal -Scope CurrentUser
ProjectRoot | -- PingModule | -- 1.0.0 | -- PingModule.psd1 | -- PingModule.psm1 | -- 1.0.1 | -- PingModule.psd1 | -- PingModule.psm1
PS /> Publish-Module -Path ./PingModule/1.0.0 -Repository PSLocal PS /> Publish-Module -Path ./PingModule/1.0.1 -Repository PSLocal
PS /> Install-Module -Name PingModule -Repository PSLocal -Scope CurrentUser PS /> Get-InstalledModule -Name PingModule Version Name Repository Description ------- ---- ---------- ----------- 1.0.1 PingModule PSLocal Get-PingReply is a.
ساختار مناسب برای ایجاد ماژولها
برای توسعه ماژولهای PowerShell توصیه میشود که از ساختار Multi-file layout استفاده شود به این معنا که بخشهای مختلف پروژه به قسمتهای کوچکتر و قابلنگهداری تقسیم شوند:
ProjectRoot | -- PingModule | -- 1.0.0 | -- Public/ | -- Private/ | -- PingModule.psd1 | -- PingModule.psm1
$ScriptList = Get-ChildItem -Path $PSScriptRoot/Public/*.ps1 -Filter *.ps1 foreach ($Script in $ScriptList) { . $Script.FullName } $ScriptList = Get-ChildItem -Path $PSScriptRoot/Private/*.ps1 -Filter *.ps1 foreach ($Script in $ScriptList) { . $Script.FullName }
یک مثال عملی
در ادامه میخواهیم یک ماژول تهیه کنیم که قابلیت امضاء روی PDF را با کمک کتابخانه iTextSharp.LGPLv2.Core انجام دهیم و به شکل زیر برای کاربر قابل استفاده باشد:
PS /> Set-PDFSingature -PdfToSign "./sample_invoice.pdf" -SignatureImage "./sample_signature.jpg"
ProjectRoot | -- SignPdf | -- 1.0.0 | -- Public/ | -- dependencies/ | -- BouncyCastle.Crypto.dll | -- System.Drawing.Common.dll | -- Microsoft.Win32.SystemEvents.dll | -- iTextSharp.LGPLv2.Core.dll | -- Set-PDFSingature.ps1 | -- SignPdf.psd1 | -- SignPdf.psm1
$ScriptList = Get-ChildItem -Path $PSScriptRoot/Public/*.ps1 -Filter *.ps1 foreach ($Script in $ScriptList) { . $Script.FullName } Export-ModuleMember -Function Set-PDFSingature
using namespace iTextSharp.text using namespace iTextSharp.text.pdf using namespace System.IO Function Set-PDFSingature { [CmdletBinding()] Param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateScript({ if (Test-Path ([Path]::Join($(Get-Location), $_))) { return $true } else { throw "Signature image not found" } if ($_.EndsWith('.pdf')) { return $true } else { throw "File extension must be .pdf" } })] [string]$PdfToSign, [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateScript({ if (Test-Path ([Path]::Join($(Get-Location), $_))) { return $true } else { throw "Signature image not found" } if ($_.EndsWith('.png') -or $_.EndsWith('.jpg')) { return $true } else { throw "File extension must be .png or .jpg" } })] [string]$SignatureImage, [Parameter(Mandatory = $false, ValueFromPipeline = $true)] [int]$XPos = 130, [Parameter(Mandatory = $false, ValueFromPipeline = $true)] [int]$YPos = 50 ) Try { Add-Type -Path "$PSScriptRoot/dependencies/*.dll" $pdf = [PdfReader]::new("$(Get-Location)/$PdfToSign") $fs = [FileStream]::new("$(Get-Location)/$PdfToSign-signed.pdf", [FileMode]::Create) $stamper = [PdfStamper]::new($pdf, $fs) $stamper.AcroFields.AddSubstitutionFont([BaseFont]::CreateFont()) $content = $stamper.GetOverContent(1) $width = $pdf.GetPageSize(1).Width $image = [Image]::GetInstance("$(Get-Location)/$SignatureImage") $image.SetAbsolutePosition($width - $XPos, $YPos) $image.ScaleAbsolute(100, 30) $content.AddImage($image) $stamper.Close() $pdf.Close() $fs.Dispose() } Catch { Write-Host "Error: $($_.Exception.Message)" } }
PS /> Publish-Module -Path ./SignPdf/1.0.0 -Repository PSLocal
PS /> Install-Module -Name SignPdf -Repository PSLocal -Scope CurrentUser
PS /> Set-PDFSingature -PdfToSign "./sample_invoice.pdf" -SignatureImage "./sample_signature.jpg"
کدهای ماژول را میتوانید از اینجا دانلود کنید.
اشتراکها
انتشار Metro Studio نسخه 5
اشتراکها
مثال هایی از نحوه نوشتن PBI
News
- As a site visitor, I can read current news on the home page.
- As a site visitor, I can access old news that is no longer on the home page.
- As a site visitor, I can email news items to the editor. (Note: this could just be an email link to
- the editor.)
- As a site a site editor, I can set the following dates on a news item: Start Publishing Date, Old
- News Date, Stop Publishing Date. These dates refer to the date an item becomes visible on the site (perhaps next Monday), the date it stops appearing on the home page, and the date it is removed from the site (which may be never).
- As a site member, I can subscribe to an RSS feed of news (and events? Or are they separate?).
- As a site editor, I can assign priority numbers to news items. Items are displayed on the front page based on priority.
نظرات اشتراکها
اهمیت محل فراخوانی OrderBy و Distinct
ممنون از مطالبتون.
من برنامه ای شبیه زیر نوشته ام:
سوالی که داشتم اینه چرا با وجود متد Distinct دستورات فوق، سه رکورد را بر میگرداند؟
من برنامه ای شبیه زیر نوشته ام:
class MainClass { class Student { public string Name { get; set; } public int Age { get; set; } } static void Main() { List<Student> s = new List<Student>() { new Student(){Name="A",Age=12}, new Student(){Name="B",Age=10}, new Student(){Name="A",Age=5}, new Student(){Name="A",Age=6}, }.ToList(); var model = s.Where(x => x.Name.Contains("A")).Distinct().OrderBy(x => x.Age).ToList(); Console.Read(); } }
سوالی که داشتم اینه چرا با وجود متد Distinct دستورات فوق، سه رکورد را بر میگرداند؟
مسیرراهها
آشنایی با Refactoring
مقالات مرتبط