Azure PowerShell: Meist harmlos

Bild 6

Hallo an alle. Heute haben wir ein weiteres Microsoft-Projekt auf dem Prüfstand. Anhand des Titels dieses Artikels können Sie sich vorstellen, dass die Entwickler uns diesmal nicht mit einer großen Anzahl von Fehlern "gefallen" haben. Wir hoffen, dass die Autoren des Projekts vom Titel nicht beleidigt werden. Immerhin ist eine kleine Anzahl von Fehlern großartig, nicht wahr? Es ist uns jedoch immer noch gelungen, im Azure PowerShell-Code etwas Interessantes zu finden. Wir empfehlen, die Funktionen dieses Projekts kennenzulernen und Fehler zu überprüfen, die mit dem PVS-Studio C # -Analysator festgestellt wurden.

Über das Projekt


Azure PowerShell ist eine Reihe von Commandlets ( Cmdlet ), mit denen Sie Azure- Ressourcen direkt über die PowerShell- Befehlszeile verwalten können. Der Hauptzweck dieses Sets besteht darin, den Lernprozess zu vereinfachen und die Entwicklung für Azure schnell zu starten. Azure PowerShell bietet Administratoren und Entwicklern überzeugende Funktionen zum Erstellen, Bereitstellen und Verwalten von Microsoft Azure-Anwendungen.

Azure PowerShell wurde in der .NET Standard-Umgebung entwickelt und wird von PowerShell 5.1 für Windows und PowerShell 6.x und höher für alle Plattformen unterstützt. Der Azure PowerShell- Quellcode ist auf GitHub verfügbar.

In letzter Zeit habe ich oft Microsoft-Projekte zur Überprüfung erhalten. Meiner Meinung nach ist die Qualität dieser Projekte in der Regel erstklassig. Obwohl natürlich nicht ohne Ausnahmen, wie im Artikel " WinForms: Errors, Holmes " beschrieben. Aber diesmal ist alles in Ordnung. Das Projekt ist groß: 6845 .cs-Quellcodedateien enthalten ungefähr 700.000 Zeilen, ausgenommen leere (ich habe Tests und Warnungen der dritten Sicherheitsstufe nicht berücksichtigt). Für diese Codemenge wurden nur sehr wenige Fehler gefunden: nicht mehr als hundert. Es gab ziemlich viele ähnliche Fälle, deshalb habe ich die interessantesten für den Artikel ausgewählt. Wie üblich habe ich Fehler nach den Nummern der PVS-Studio-Warnungen sortiert.

Außerdem bin ich auf einige Codefragmente gestoßen, die wie Fehler aussahen, aber nicht als definitiv fehlerhaft erkannt werden konnten, da ich mit den Besonderheiten der PowerShell-Entwicklung nicht vertraut genug bin. Ich hoffe, dass es unter den Lesern Spezialisten in dieser Ausgabe gibt, die mir helfen werden. Ich werde es unten im Detail beschreiben.

Vor dem Feedback-Teil möchte ich die spezifische Struktur des Projekts erwähnen. Der Azure PowerShell-Quellcode besteht aus mehr als siebzig Visual Studio-Lösungen. Einige Lösungen umfassen Projekte von anderen. Diese Struktur verlangsamte die Analyse ein wenig (nicht viel). Trotzdem verursachte der Scheck keine weiteren Schwierigkeiten. Der Einfachheit halber werde ich in der Fehlermeldung (in Klammern) den Namen der Lösung angeben, bei der der Fehler gefunden wurde.

Analyseergebnisse


V3001 Links und rechts vom '||' befinden sich identische Unterausdrücke 'strTimespan.Contains ("M")'. Betreiber. AzureServiceBusCmdletBase.cs 187 (EventGrid)

public static TimeSpan ParseTimespan(string strTimespan) { .... if (strTimespan.Contains("P") || strTimespan.Contains("D") || strTimespan.Contains("T") || strTimespan.Contains("H") || strTimespan.Contains("M") || strTimespan.Contains("M")) .... } 

Ein Beispiel für einen ziemlich offensichtlichen Fehler, den nur ein Entwickler beheben kann. In diesem Fall ist es absolut unklar, ob es sich bei einer von zwei letzten Prüfungen um Codeduplizierungen handelt, die nichts betreffen oder etwas anderes anstelle von "M" stattfinden müssen .

V3001 Links und rechts vom Operator '&&' befinden sich identische Unterausdrücke 'this.AggregationType! = Null'. GetAzureRmMetricCommand.cs 156 (Monitor)

 public AggregationType? AggregationType { get; set; } .... protected override void ProcessRecordInternal() { .... string aggregation = (this.AggregationType != null && this.AggregationType.HasValue) ? this.AggregationType.Value.ToString() : null; .... } 

Hier liegt wahrscheinlich kein Fehler vor. Dies ist ein Beispiel für redundanten Code. Manchmal weist ein solcher Code auf mangelndes Wissen des Entwicklers hin. Der Punkt ist, dass die Prüfungen this.AggregationType! = Null und this.AggregationType.HasValue identisch sind. Es reicht aus, nur einen von ihnen (einen) zu verwenden. Persönlich bevorzuge ich die Option mit HasValue:

 string aggregation = this.AggregationType.HasValue ? this.AggregationType.Value.ToString() : null; 

V3003 Die Verwendung des Musters 'if (A) {...} else if (A) {...}' wurde erkannt. Es besteht die Wahrscheinlichkeit eines logischen Fehlers. Überprüfen Sie die Zeilen: 152, 163. GetAzureRmRecoveryServicesBackupProtectionPolicy.cs 152 (RecoveryServices)

 public override void ExecuteCmdlet() { .... if( WorkloadType == Models.WorkloadType.AzureVM ) { .... } .... else if( WorkloadType == Models.WorkloadType.AzureFiles ) { if( BackupManagementType != Models.BackupManagementType.AzureStorage ) { throw new ArgumentException( Resources.AzureFileUnsupportedBackupManagementTypeException ); } serviceClientProviderType = ServiceClientHelpers. GetServiceClientProviderType( Models.WorkloadType.AzureFiles ); } else if( WorkloadType == Models.WorkloadType.AzureFiles ) { if( BackupManagementType != Models.BackupManagementType.AzureStorage ) { throw new ArgumentException( Resources.AzureFileUnsupportedBackupManagementTypeException ); } serviceClientProviderType = ServiceClientHelpers. GetServiceClientProviderType( Models.WorkloadType.AzureFiles ); } .... } 

Zwei weitere, wenn Blöcke absolut identisch sind, einschließlich des Zustands und des Körpers des Blocks. Solche Fehler treten normalerweise bei Verwendung der Copy-Paste-Methode auf. Das Problem hier ist wieder die Kritikalität des Fehlers. Wenn es sich nicht um eine einfache Codeduplizierung handelt, kann es sich um die fehlende erforderliche Überprüfung und die entsprechenden Maßnahmen handeln. Der Autor muss den Code definitiv bearbeiten.

V3005 Die Variable 'this.VM.OSProfile.WindowsConfiguration.ProvisionVMAgent' wird sich selbst zugewiesen. SetAzureVMOperatingSystemCommand.cs 298 (Compute)

 public override void ExecuteCmdlet() { .... // OS Profile this.VM.OSProfile.WindowsConfiguration.ProvisionVMAgent = this.VM.OSProfile.WindowsConfiguration.ProvisionVMAgent; .... } 

Der Wert der Eigenschaft wird selbst zugewiesen. Schauen Sie sich die Erklärung an:

 [JsonProperty(PropertyName = "provisionVMAgent")] public bool? ProvisionVMAgent { get; set; } 

In der JsonProperty- Beschreibung heißt es: "Weist den Newtonsoft.Json.JsonSerializer an, das Mitglied immer mit dem angegebenen Namen zu serialisieren." Es scheint, dass alles schuldlos ist und der offensichtliche Fehler gemacht wurde. Die explizite Verwendung dieser Option für den Zugriff auf die Immobilie ist ebenfalls ziemlich verwirrend. Vielleicht wurde stattdessen nicht fälschlicherweise eine andere Variable angegeben . Aber lassen Sie uns nicht zu Schlussfolgerungen springen. Tatsache ist, dass ich auf eine Menge solcher Aufgaben gestoßen bin (eine Eigenschaft ist selbst zugewiesen). Hier ist ein Beispiel für eine Zuweisung, die einem Fehler sehr ähnlich ist:

V3005 Die Variable 'this.LastHeartbeat' wird sich selbst zugewiesen. PSFabricDetails.cs 804 (RecoveryServices)

 public ASRInMageAzureV2SpecificRPIDetails( InMageAzureV2ReplicationDetails details) { this.LastHeartbeat = this.LastHeartbeat; // <= this.RecoveryAvailabilitySetId = details.RecoveryAvailabilitySetId; this.AgentVersion = details.AgentVersion; this.DiscoveryType = details.DiscoveryType; .... } 

Schauen wir uns die zweite und die nachfolgenden Aufgaben genauer an. Im rechten Teil des Ausdrucks finden stattdessen Details statt . Schauen Sie sich nun die Deklaration der Eigenschaft this.LastHeartbeat an :
 public DateTime? LastHeartbeat { get; set; } 

Zuletzt suchen wir die gleichnamige Eigenschaft in der InMageAzureV2ReplicationDetails- Klasse. Ein solches Eigentum wird dort deklariert:

 public class InMageAzureV2ReplicationDetails : ReplicationProviderSpecificSettings { .... [JsonProperty(PropertyName = "lastHeartbeat")] public DateTime? LastHeartbeat { get; set; } .... } 

Nun, in diesem Fall bin ich bereit zuzugeben, dass es ein echter Fehler ist. Aber was sollen wir mit den nächsten Warnungen tun? Im Gegensatz zu zwei vorherigen Codefragmenten gibt es mehrere selbst zugewiesene Eigenschaften. Nun, das sieht weniger nach einem Fehler aus:

  • V3005 Die Variable 'this.ResourceGroupName' wird sich selbst zugewiesen. RemoveAzureRmExpressRouteConnectionCommand.cs 84 (CognitiveServices)
  • V3005 Die Variable 'this.ExpressRouteGatewayName' wird sich selbst zugewiesen. RemoveAzureRmExpressRouteConnectionCommand.cs 85 (CognitiveServices)
  • V3005 Die Variable 'this.Name' wird sich selbst zugewiesen. RemoveAzureRmExpressRouteConnectionCommand.cs 86 (CognitiveServices)

 [Cmdlet(VerbsCommon.Remove, ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "ExpressRouteConnection", DefaultParameterSetName = CortexParameterSetNames.ByExpressRouteConnectionName, SupportsShouldProcess = true), OutputType(typeof(bool))] public class RemoveExpressRouteConnectionCommand : ExpressRouteConnectionBaseCmdlet { [Parameter( Mandatory = true, ParameterSetName = CortexParameterSetNames.ByExpressRouteConnectionName, HelpMessage = "The resource group name.")] [ResourceGroupCompleter] [ValidateNotNullOrEmpty] public string ResourceGroupName { get; set; } .... public override void Execute() { if (....) { this.ResourceGroupName = this.ResourceGroupName; this.ExpressRouteGatewayName = this.ExpressRouteGatewayName; this.Name = this.Name; } .... } .... } 

Die Execute- Methode enthält die Selbstzuweisungen von drei Eigenschaften in einer Reihe. Für alle Fälle habe ich die vollständige Deklaration der Klasse RemoveExpressRouteConnectionCommand und aller ihrer Attribute sowie die ResourceGroupName- Eigenschaftsdeklaration zitiert (die beiden anderen Eigenschaften werden auf ähnliche Weise deklariert). Es waren diese Warnungen, die mich über die Frage nachdenken ließen: "Ist es ein Fehler?" Ich vermute, dass hier eine interne Magie der PowerShell-Entwicklung stattfindet. Ich hoffe, dass es unter den Lesern Experten gibt, die über dieses Thema informiert sind. Ich bin nicht bereit, in diesem Fall irgendwelche Schlussfolgerungen zu ziehen.

V3006 Das Objekt wurde erstellt, wird jedoch nicht verwendet. Das Schlüsselwort 'throw' könnte fehlen: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrTestFailoverJob.cs 259 (RecoveryServices)

 private void StartRPITestFailover() { .... if (....) { .... } else { new ArgumentException( Resources .UnsupportedDirectionForTFO); // Throw Unsupported Direction // Exception } .... } 

Das Schlüsselwort throw wird weggelassen. Und der Kommentar besagt, dass die Ausnahme nur ausgelöst werden muss. In der RecoveryServices- Lösung sind mehrere ähnliche Fehler aufgetreten:

  • V3006 Das Objekt wurde erstellt, wird jedoch nicht verwendet. Das Schlüsselwort 'throw' könnte fehlen: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrTestFailoverJob.cs 305 (RecoveryServices)
  • V3006 Das Objekt wurde erstellt, wird jedoch nicht verwendet. Das Schlüsselwort 'throw' könnte fehlen: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrUnPlannedFailover.cs 278 (RecoveryServices)
  • V3006 Das Objekt wurde erstellt, wird jedoch nicht verwendet. Das Schlüsselwort 'throw' könnte fehlen: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrUnPlannedFailover.cs 322 (RecoveryServices)
  • V3006 Das Objekt wurde erstellt, wird jedoch nicht verwendet. Das Schlüsselwort 'throw' könnte fehlen: throw new ArgumentException (FOO). UpdateAzureRmRecoveryServicesAsrProtectionDirection.cs 421 (RecoveryServices)
  • V3006 Das Objekt wurde erstellt, wird jedoch nicht verwendet. Das Schlüsselwort 'throw' könnte fehlen: throw new ArgumentException (FOO). UpdateAzureRmRecoveryServicesAsrProtectionDirection.cs 452 (RecoveryServices)

V3022 Der Ausdruck 'apiType.HasValue' ist immer falsch. ApiManagementClient.cs 1134 (ApiManagement)

 private string GetApiTypeForImport(...., PsApiManagementApiType? apiType) { .... if (apiType.HasValue) { switch(apiType.Value) { case PsApiManagementApiType.Http: return SoapApiType.SoapToRest; case PsApiManagementApiType.Soap: return SoapApiType.SoapPassThrough; default: return SoapApiType.SoapPassThrough; } } return apiType.HasValue ? // <= apiType.Value.ToString("g") : PsApiManagementApiType.Http.ToString("g"); } 

Die Logik der Arbeit wurde gebrochen. Wenn apiType einen Wert enthält, erreicht das Steuerelement den Rückgabeausdruck am Ende der Methode nicht (alle Switch- Zweige enthalten return ). Andernfalls gibt die Methode immer PsApiManagementApiType.Http.ToString ("g") zurück , während der Wert apiType.Value.ToString ("g") niemals zurückgegeben wird.

V3022 Der Ausdruck 'automationJob! = Null && automationJob == null' ist immer falsch. NodeConfigurationDeployment.cs 199 (Automatisierung)

 public NodeConfigurationDeployment( ...., Management.Automation.Models.Job automationJob = null, ....) { .... if (automationJob != null && automationJob == null) return; .... } 

Kontraintuitiver Code. Zwei Schecks, die sich widersprechen. Wahrscheinlich enthält die zweite Prüfung auf null die falsche Variable.

V3022 Ausdruck ist immer falsch. DataFactoryClient.Encrypt.cs 37 (DataFactory)

 public virtual string OnPremisesEncryptString(....) { .... if ( linkedServiceType == LinkedServiceType.OnPremisesSqlLinkedService && linkedServiceType == LinkedServiceType.OnPremisesOracleLinkedService && linkedServiceType == LinkedServiceType.OnPremisesFileSystemLinkedService && (value == null || value.Length == 0)) { throw new ArgumentNullException("value"); } .... } 

Die Prüfung ist sinnlos und die Ausnahme wird niemals ausgelöst. Die Bedingung erfordert die gleichzeitige Gleichheit der Variablen linkedServiceType mit drei verschiedenen Werten. Die Operatoren && und || sind wahrscheinlich verwirrt. Fester Code:

 if (( linkedServiceType == LinkedServiceType.OnPremisesSqlLinkedService || linkedServiceType == LinkedServiceType.OnPremisesOracleLinkedService || linkedServiceType == LinkedServiceType.OnPremisesFileSystemLinkedService) && (value == null || value.Length == 0)) .... 

V3022 Der Ausdruck 'Ekus == null' ist immer falsch. PSKeyVaultCertificatePolicy.cs 129 (KeyVault)

 internal CertificatePolicy ToCertificatePolicy() { .... if (Ekus != null) { x509CertificateProperties.Ekus = Ekus == null ? null : new List<string>(Ekus); } .... } 

Redundante Überprüfung der Ekus- Variablen auf Null . Es ist wahrscheinlich in Ordnung, aber der Code sieht nicht gut aus.

V3023 Überprüfen Sie diesen Ausdruck. Der Ausdruck ist übertrieben oder enthält einen Druckfehler. PolicyRetentionObjects.cs 207 (RecoveryServices)

 public virtual void Validate() { if (RetentionTimes == null || RetentionTimes.Count == 0 || RetentionTimes.Count != 1) { throw new ArgumentException( Resources.InvalidRetentionTimesInPolicyException); } } 

Hier ist eine übermäßige Überprüfung oder ein übermäßiger Zustand. Die Prüfung RetentionTimes.Count == 0 ist sinnlos, da danach die Prüfung RetentionTimes.Count! = 1 folgt.

V3025 Falsches Format. Beim Aufrufen der Funktion 'Format' wird eine andere Anzahl von Formatelementen erwartet. Nicht verwendete Argumente: this.ResourceGroupName. NewScheduledQueryRuleCommand.cs 117 (Monitor)

 protected override void ProcessRecordInternal() { .... if (this.ShouldProcess(this.Name, string.Format("Creating Log Alert Rule '{0}' in resource group {0}", this.Name, this.ResourceGroupName))) { .... } .... } 

Ein Fehler in der Formatierungszeile. Der Bezeichner {0} wird zweimal verwendet, und der Format- Methode werden zwei Argumente übergeben. Hier ist die richtige Version:

 if (this.ShouldProcess(this.Name, string.Format("Creating Log Alert Rule '{0}' in resource group {1}", this.Name, this.ResourceGroupName))) .... 

Ein weiterer ähnlicher Fehler:

  • V3025 Falsches Format. Beim Aufrufen der Funktion 'Format' wird eine andere Anzahl von Formatelementen erwartet. Nicht verwendete Argumente: this.ResourceGroupName. RemoveScheduledQueryRuleCommand.cs 88 (Monitor)

V3042 Mögliche NullReferenceException. Das '?.' und '.' Operatoren werden für den Zugriff auf Mitglieder des Objekts 'imageAndOsType' VirtualMachineScaleSetStrategy.cs 81 (Compute) verwendet.

 internal static ResourceConfig<VirtualMachineScaleSet> CreateVirtualMachineScaleSetConfig(...., ImageAndOsType imageAndOsType, ....) { .... VirtualMachineProfile = new VirtualMachineScaleSetVMProfile { OsProfile = new VirtualMachineScaleSetOSProfile { ...., WindowsConfiguration = imageAndOsType.CreateWindowsConfiguration(), // <= ...., }, StorageProfile = new VirtualMachineScaleSetStorageProfile { ImageReference = imageAndOsType?.Image, // <= DataDisks = DataDiskStrategy.CreateVmssDataDisks( imageAndOsType?.DataDiskLuns, dataDisks) // <= }, }, .... } 

Beim Erstellen des VirtualMachineScaleSetVMProfile- Objekts wird die Variable imageAndOsType ohne vorherige Überprüfung auf null überprüft. Beim Erstellen von VirtualMachineScaleSetStorageProfile wird diese Variable jedoch bereits zweimal mit dem Operator für bedingten Zugriff überprüft. Der Code sieht nicht sicher aus.

V3042 Mögliche NullReferenceException. Das '?.' und '.' Operatoren werden für den Zugriff auf Mitglieder des Objekts 'availableContacts' verwendet. RemoveAzureKeyVaultCertificateContact.cs 123 (KeyVault)

 public override void ExecuteCmdlet() { .... List<PSKeyVaultCertificateContact> existingContacts; try { existingContacts = this.DataServiceClient. GetCertificateContacts(VaultName)?.ToList(); } catch (KeyVaultErrorException exception) { .... existingContacts = null; } foreach (var email in EmailAddress) { existingContacts.RemoveAll(....); // <= } .... } 

Sowohl bei der normalen Ausführung als auch als Ergebnis der Behandlung einer Ausnahme kann die Variable existierende Kontakte den Nullwert erhalten , wonach die Ausführung fortgesetzt wird. Weiter im Code wird diese Variable ohne besonderen Grund verwendet.

V3066 Möglicherweise falsche Reihenfolge der an die Methode 'PersistSyncServerRegistration' übergebenen Argumente: 'storageSyncServiceUid' und 'DiscoveryUri'. EcsManagementInteropClient.cs 364 (StorageSync)

 public class EcsManagementInteropClient : IEcsManagement { .... public int PersistSyncServerRegistration(....) { return m_managementObject.PersistSyncServerRegistration( serviceUri, subscriptionId, storageSyncServiceName, resourceGroupName, clusterId, clusterName, storageSyncServiceUid, // <= discoveryUri, // <= serviceLocation, resourceLocation); } .... } 

Der Analysator vermutete, dass die Reihenfolge der Argumente der PersistSyncServerRegistration- Methode verwirrt ist. Erklärung der Methode:

 public interface IEcsManagement : IDisposable { .... int PersistSyncServerRegistration( [In, MarshalAs(UnmanagedType.BStr)] string serviceUri, [In, MarshalAs(UnmanagedType.BStr)] string subscriptionId, [In, MarshalAs(UnmanagedType.BStr)] string storageSyncServiceName, [In, MarshalAs(UnmanagedType.BStr)] string resourceGroupName, [In, MarshalAs(UnmanagedType.BStr)] string clusterId, [In, MarshalAs(UnmanagedType.BStr)] string clusterName, [In, MarshalAs(UnmanagedType.BStr)] string discoveryUri, // <= [In, MarshalAs(UnmanagedType.BStr)] string storageSyncServiceUid, // <= [In, MarshalAs(UnmanagedType.BStr)] string serviceLocation, [In, MarshalAs(UnmanagedType.BStr)] string resourceLocation); .... } 

In der Tat stimmt hier etwas mit den Argumenten Nummer sieben und acht nicht. Der Autor muss den Code überprüfen.

V3077 Der Setter der Eigenschaft 'GetGuid' verwendet seinen Parameter 'value' nicht. RecoveryServicesBackupCmdletBase.cs 54 (RecoveryServices)

 public abstract class RecoveryServicesBackupCmdletBase : AzureRMCmdlet { .... static string _guid; protected static string GetGuid { get { return _guid; } set { _guid = Guid.NewGuid().ToString(); } } .... } 

Der Setter verwendet den übergebenen Parameter nicht. Stattdessen wird eine neue GUID erstellt und dem Feld _guid zugewiesen . Ich denke, die meisten Leser würden zustimmen, dass ein solcher Code zumindest hässlich aussieht. Diese Konstruktion ist nicht sehr bequem zu verwenden: Wenn die GetGuid- Eigenschaft (neu) initialisiert wird, muss ihr ein gefälschter Wert zugewiesen werden, was nicht sehr offensichtlich ist. Vor allem aber hat mich die Art und Weise, wie Autoren dieses Muster verwendeten, amüsiert. Es gibt nur einen Ort, an dem GetGuid verwaltet wird. Probieren Sie es aus:

 public override void ExecuteCmdlet() { .... var itemResponse = ServiceClientAdapter.CreateOrUpdateProtectionIntent( GetGuid ?? Guid.NewGuid().ToString(), ....); .... } 

Genial!

V3091 Empirische Analyse. Möglicherweise ist im Zeichenfolgenliteral ein Tippfehler vorhanden: "Verwaltungsgruppen-ID". Das 'Id'-Wort ist verdächtig. Constants.cs 36 (Ressourcen)

 public class HelpMessages { public const string SubscriptionId = "Subscription Id of the subscription associated with the management"; public const string GroupId = "Management Group Id"; // <= public const string Recurse = "Recursively list the children of the management group"; public const string ParentId = "Parent Id of the management group"; public const string GroupName = "Management Group Id"; // <= public const string DisplayName = "Display Name of the management group"; public const string Expand = "Expand the output to list the children of the management group"; public const string Force = "Force the action and skip confirmations"; public const string InputObject = "Input Object from the Get call"; public const string ParentObject = "Parent Object"; } 

Der Analysator hat auf einen möglichen Fehler in der zugewiesenen Zeichenfolge für die GroupName- Konstante hingewiesen . Die Schlussfolgerung basiert auf einer empirischen Analyse anderer Zuordnungen unter Berücksichtigung der Namen von Variablen. Ich denke, dass in diesem Fall der Analysator richtig ist und der Wert der GroupName- Konstanten eine Art "Management Group Name" sein sollte. Wahrscheinlich ist der Fehler darauf zurückzuführen, dass der Wert für die GroupId- Konstante kopiert, aber nicht geändert wurde.

Ein weiterer ähnlicher Fehler:

  • V3091 Empirische Analyse. Möglicherweise ist im Zeichenfolgenliteral ein Tippfehler vorhanden. Das Wort 'Name' ist verdächtig. ParamHelpMsgs.cs 153 (RecoveryServices)

V3093 Das '|' Der Operator wertet beide Operanden aus. Vielleicht ein Kurzschluss '||' Stattdessen sollte der Operator verwendet werden. PSKeyVaultCertificatePolicy.cs 114 (KeyVault)

 internal CertificatePolicy ToCertificatePolicy() { .... if (!string.IsNullOrWhiteSpace(SubjectName) || DnsNames != null || Ekus != null || KeyUsage != null | // <= ValidityInMonths.HasValue) { .... } .... } 

In diesem Fragment kann ein Fehler auftreten und im if- Block zwischen zwei letzten Bedingungen das || Möglicherweise wurde der Operator verwendet. Aber wie so oft kann nur der Entwickler die richtige Antwort geben.

V3095 Das 'Zertifikat'-Objekt wurde verwendet, bevor es gegen Null verifiziert wurde. Überprüfen Sie die Zeilen: 41, 43. CertificateInfo.cs 41 (Automatisierung)

 public CertificateInfo( ...., Azure.Management.Automation.Models.Certificate certificate) { .... this.Name = certificate.Name; if (certificate == null) return; .... } 

Klassisch. Zuerst wird das Objekt verwendet und erst danach wird die Referenz auf Null geprüft. Wir stoßen sehr oft auf solche Fehler. Betrachten wir einen weiteren ähnlichen Fehler.

V3095 Das Objekt 'clusterCred' wurde verwendet, bevor es gegen null verifiziert wurde. Überprüfen Sie die Zeilen: 115, 118. InvokeHiveCommand.cs 115 (HDInsight)

 public override void ExecuteCmdlet() { .... _credential = new BasicAuthenticationCloudCredentials { Username = clusterCred.UserName, Password = clusterCred.Password.ConvertToString() }; if (clusterConnection == null || clusterCred == null) .... } 

Hier sind einige ähnliche Fehler:

  • V3095 Das Objekt '_profile' wurde verwendet, bevor es gegen null verifiziert wurde. Überprüfen Sie die Zeilen: 47, 49. RMProfileClient.cs 47 (Konten)
  • V3095 Das Objekt 'this.LoadBalancer.BackendAddressPools' wurde verwendet, bevor es gegen null verifiziert wurde. Überprüfen Sie die Zeilen: 56, 63. AddAzureRmLoadBalancerBackendAddressPoolConfigCommand.cs 56 (CognitiveServices)
  • Im Allgemeinen wurden im Azure PowerShell-Code viele V3095- Fehler angezeigt . Aber alle sind sich ziemlich ähnlich, deshalb werde ich mich nicht mit diesem Thema befassen.

V3125 Das 'startTime'-Objekt wurde verwendet, nachdem es gegen null verifiziert wurde. Überprüfen Sie die Zeilen: 1752, 1738. AutomationPSClientDSC.cs 1752 (Automation)

 private string GetNodeReportListFilterString( ...., DateTimeOffset? startTime, ...., DateTimeOffset? lastModifiedTime) { .... if (startTime.HasValue) { odataFilter.Add("properties/startTime ge " + this.FormatDateTime(startTime.Value)); // <= } .... if (lastModifiedTime.HasValue) { odataFilter.Add("properties/lastModifiedTime ge " + this.FormatDateTime(startTime.Value)); // <= } .... } 

Es ist auch eine ziemlich weit verbreitete Art von Fehlern. Die Variable startTime wird bei der ersten Verwendung auf das Vorhandensein eines Werts überprüft. Dies erfolgt jedoch nicht in der nachfolgenden Verwendung. Nun, die Situation kann noch schlimmer sein. Schauen Sie sich den zweiten if- Block an. Ich denke, die Variable startTime darf überhaupt nicht hier sein. Erstens gibt es keine Überprüfung auf das Vorhandensein eines Werts vor seiner Verwendung. Zweitens bestätigt die Zeichenfolge, die gebildet wird, um an die Add- Methode übergeben zu werden, meinen Vorschlag. Eine weitere Variable (lastModifiedTime ) wird im ersten Teil dieser Zeichenfolge erwähnt.

V3125 Das 'firstPage'-Objekt wurde verwendet, nachdem es gegen null verifiziert wurde. Überprüfen Sie die Zeilen: 113, 108. IntegrationAccountAgreementOperations.cs 113 (LogicApp)

 public IList<IntegrationAccountAgreement> ListIntegrationAccountAgreements(....) { var compositeList = new List<IntegrationAccountAgreement>(); var firstPage = this.LogicManagementClient. IntegrationAccountAgreements.List(....); if (firstPage != null) { compositeList.AddRange(firstPage); } if (!string.IsNullOrEmpty(firstPage.NextPageLink)) // <= { .... } .... } 

Ein weiterer offensichtlicher Fehler. Die Variable firstPage wird unsicher verwendet, obwohl diese Variable bereits früher im Code verwendet wurde und vorläufig auf null überprüft wurde.

Ich habe im Azure PowerShell-Code noch mehr V3125- Warnungen gefunden als die oben beschriebenen V3095- Warnungen. Alle von ihnen sind auch vom gleichen Typ. Ich denke, zwei davon, die wir in Betracht gezogen haben, sind genug.

V3137 Die Variable 'apiVersionSetId' wird zugewiesen, aber am Ende der Funktion nicht verwendet. GetAzureApiManagementApiVersionSet.cs 69 (ApiManagement)

 public String ApiVersionSetId { get; set; } .... public override void ExecuteApiManagementCmdlet() { .... string apiVersionSetId; if (ParameterSetName.Equals(ContextParameterSet)) { .... apiVersionSetId = ApiVersionSetId; } else { apiVersionSetId = ....; } if (string.IsNullOrEmpty(ApiVersionSetId)) // <= { WriteObject(....); } else { WriteObject(Client.GetApiVersionSet(...., ApiVersionSetId)) // <= } } 

Der Analysator meldet, dass die lokale Variable apiVersionSetId initialisiert, aber in keiner Weise verwendet wurde. Oft weist dieses Muster auf einen Fehler hin. Ich denke, in diesem Fall handelt es sich höchstwahrscheinlich um einen Fehler, insbesondere unter Berücksichtigung der Tatsache, dass sich der Name der lokalen Variablen apiVersionSetId und der Name der Eigenschaft ApiVersionSetId nur durch den Fall des ersten Buchstabens unterscheiden. Schauen Sie sich den Code an. Nach der Initialisierung der apiVersionSetId-Eigenschaft (auf die eine oder andere Weise) wird im Code nur die ApiVersionSetId- Eigenschaft weiter verwendet. Es sieht sehr verdächtig aus.

V3137 Die Variable 'cacheId' wird zugewiesen, aber am Ende der Funktion nicht verwendet. RemoveAzureApiManagementCache.cs 94 (ApiManagement)

 public String CacheId { get; set; } .... public override void ExecuteApiManagementCmdlet() { .... string cacheId; if (....) { .... cacheId = InputObject.CacheId; } else if (....) { .... cacheId = cache.CacheId; } else { .... cacheId = CacheId; } var actionDescription = string.Format(...., CacheId); // <= var actionWarning = string.Format(...., CacheId); // <= .... Client.CacheRemove(resourceGroupName, serviceName, CacheId); // <= .... } 

Dies ist der Fall, der fast der gleiche ist wie der zuvor beschriebene. Die lokale Variable cacheId wird nach der Initialisierung in keiner Weise verwendet. Stattdessen wird eine andere Eigenschaft mit einem sehr ähnlichen Namen CacheId verwendet. Ich weiß es nicht genau. Vielleicht ist das nur ein Programmiermuster von Azure PowerShell-Entwicklern. Wie auch immer, es sieht nach einem Fehler aus.

V3143 Der Parameter 'value' wird in einem Eigenschaftssetter neu geschrieben und danach nicht mehr verwendet. NewAzureIntegrationAccountPartnerCommand.cs 67 (LogicApp)

 [Parameter(Mandatory = false, HelpMessage = "The integration account partner type.", ValueFromPipelineByPropertyName = false)] [ValidateSet("B2B", IgnoreCase = false)] [ValidateNotNullOrEmpty] public string PartnerType { get { return this.partnerType; } set { value = this.partnerType; } // <= } 

Das Feld partnerType wird folgendermaßen deklariert:

 /// <summary> /// Default partner type. /// </summary> private string partnerType = "B2B"; 

Trotz des Namens der Lösung (LogicApp), bei der ein Fehler festgestellt wurde, finde ich keine Logik darin. Das Ändern des Werts im Setter ist nicht selten, aber in diesem Fall handelt es sich um einen Verlust des ursprünglichen Werts. Es sieht komisch aus. In der Code-Eigenschaft wird nur einmal gelesen. Vielleicht müssen wir noch einmal um Rat fragen. Vielleicht verstehe ich es einfach nicht. Der Punkt ist, dass ich auf mehrere gleiche Muster gestoßen bin:

  • V3143 Der Parameter 'value' wird in einem Eigenschaftssetter neu geschrieben und danach nicht mehr verwendet. NewAzureIntegrationAccountSchemaCommand.cs 79 (LogicApp)
  • V3143 Der Parameter 'value' wird in einem Eigenschaftssetter neu geschrieben und danach nicht mehr verwendet. NewAzureIntegrationAccountSchemaCommand.cs 87 (LogicApp)
  • V3143 Der Parameter 'value' wird in einem Eigenschaftssetter neu geschrieben und danach nicht mehr verwendet. UpdateAzureIntegrationAccountPartnerCommand.cs 67 (LogicApp)
  • V3143 Der Parameter 'value' wird in einem Eigenschaftssetter neu geschrieben und danach nicht mehr verwendet. UpdateAzureIntegrationAccountSchemaCommand.cs 80 (LogicApp)
  • V3143 Der Parameter 'value' wird in einem Eigenschaftssetter neu geschrieben und danach nicht mehr verwendet. UpdateAzureIntegrationAccountSchemaCommand.cs 88 (LogicApp)

Fazit


Dies sind alles interessante Fehler, die im Azure PowerShell-Code gefunden wurden. Enthusiasten und Interessierte können Fehler in diesem (oder einem anderen) Projekt gerne selbst überprüfen. Ich könnte wahrscheinlich etwas Ungewöhnliches verpassen. Um die Überprüfung durchzuführen, müssen Sie nur PVS-Studio herunterladen und installieren.

Vielen Dank für das Lesen bis zum Ende. Und natürlich fehlerfreien Code für alle!

Source: https://habr.com/ru/post/de470728/


All Articles