[Perl] Can't call method "Open" on an undefined value

Can't call method "Open" on an undefined value [Perl] - Perl - Programmation

Marsh Posté le 01-03-2012 à 13:14:51    

Bonjour,
 
Vraiment grand débutant en langage Perl, je dois utiliser StrawberryPerl en version

Citation :

This is perl 5, version 14, subversion 2 (v5.14.2) built for MSWin32-x86-multi-thread


 
Et je me trouve confronté à une erreur Can't call method "Open" on an undefined value
 
Voici la partie du code sur lequel cela bloque :
 

Citation :


# Usage:   &win32_reg_read("key", "value" )
# Example: &win32_reg_read("SOFTWARE\\Net-SNMP","SNMPSHAREPATH" );
# Returns: Value if found in HKCU or HCLM.  Otherwise an empty string.
sub win32_reg_read {
  my $sub_key = shift;
  my $value = shift;
 
  require Win32::TieRegistry;
     
  my ($hkey, %key_values, $temp, $no_warn);
 
  # Try HKCU first
  $no_warn = $HKEY_CURRENT_USER;
  if ($HKEY_CURRENT_USER->Open($sub_key, $hkey))
  {
    $hkey->GetValues(\%key_values);    
    foreach $temp (sort keys %key_values) {
      if ($temp eq $value) {
        return $key_values{$temp}[2];
      }
    }
    $hkey->Close();  
  }


 
Comment les variables $sub_key et $hkey sont alimentées ? Je ne comprend pas le shift.
 
Merci de votre aide

Reply

Marsh Posté le 01-03-2012 à 13:14:51   

Reply

Marsh Posté le 01-03-2012 à 14:54:54    

C'est très simple:
Tout sub (ie subroutine, bref, une fonction) en perl prend pour argument une liste
Si tu fais: win32_reg_read("SOFTWARE\\Net-SNMP","SNMPSHAREPATH" );  
(on met plus de & devant un nom de sub depuis des plombes, sauf dans des cas très spéciaux)
tu appelles le sub win32_reg_read avec la liste d'arguments ("SOFTWARE\\Net-SNMP", "SNMPSHAREPATH" )
La liste d'arguments à un nom implicite: @_
donc dans l'exemple, tu as un appel de win32_reg_read avec @_ = ("SOFTWARE\\Net-SNMP", "SNMPSHAREPATH" )
faire shift sans argument a l'intérieur d'un sub, c'est le faire sur @_
bref, faire  
my $sub_key = shift;
c'est faire
my $sub_key = shift @_;
ou shift a le sens habituel d'un shift sur une liste (fonction qui renvoie le premier argument de la liste, qu'il enlève de la liste)
après cet appel, $sub_key = "SOFTWARE\\Net-SNMP" et @_ = ("SNMPSHAREPATH" )
la ligne suivante faire
my $value = shift;  
c'est faire
my $value = shift @_;  
après cet appel, $value = "SNMPSHAREPATH" et @_ = ()
 
A+,
 


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 01-03-2012 à 15:05:33    

ok ok merci, je comprend je penses.
Mais alors pourquoi j'ai cette erreur de liste non alimentée ?
J'ai regardé l'ensemble du code, et je n'ai à aucun endroit l'appel à cette fonction win32_reg_read...
On est bien d'accord que dans le code, je devrais trouver à un endroit cette fonction avec comme argument, les trucs en exemple :
 
Example: &win32_reg_read("SOFTWARE\\Net-SNMP","SNMPSHAREPATH" );
 


Message édité par akizan le 01-03-2012 à 15:05:59
Reply

Marsh Posté le 01-03-2012 à 15:25:56    

Bon en cherchant, et à coup de print des variables, elles sont bien remplies par les bonnes valeurs :
subkey : SOFTWARE\Net-SNMP
value : SNMPSHAREPATH
 
Du coup, l'erreur est bidon ou quoi...

Reply

Marsh Posté le 01-03-2012 à 15:41:23    

ok j'ai compris, le code que j'ai récupéré utilise Win32::Registry alors que celui-ci n'a pas l'air d'être bien supporté par StrawberryPerl qui est remplacé par Win32::TieRegistry
=> du coup faudrait que je modifie le code :)

Reply

Marsh Posté le 01-03-2012 à 15:52:35    

L'erreur est pas bidon, si je suis bien, $HKEY_CURRENT_USER est pas initialisé (j'ai pensé au départ que ça l'était par l'importation de Win32::TieRegistry; mais ça a pas l'air au vu de la doc du module).
Il faut faire  
$HKEY_CURRENT_USER = $Registry->{"HKEY_CURRENT_USER"}; # ou $Registry->{"HKEY_CURRENT_USER\\"} ?? à tester
$Registry est lui créé a  l'importation de Win32::TieRegistry au vu de la doc
et la, comme il aura été initialisé,  
$HKEY_CURRENT_USER->Open
devrait marcher.
 
A+,


Message édité par gilou le 01-03-2012 à 15:55:59

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 01-03-2012 à 16:05:03    

Oui en fait c'est moi qui a changé Win32::Registry dans le code car ça ne marchait pas, en pensant que Win32::TieRegistry fonctionnerait pareil.
C'est beau la naïveté ^^
 
Merci de ton aide, j'essai ça.

Reply

Marsh Posté le 02-03-2012 à 08:54:20    

Merci pour ton aide mais après tests, voila ce que ça donne  :(  
 
1er test :
 

Code :
  1. sub win32_reg_read {
  2.  my $sub_key = shift;
  3.  my $value = shift;
  4.  
  5.  #require Win32::Registry;
  6.  require Win32::TieRegistry;
  7.    
  8.  my ($hkey, %key_values, $temp, $no_warn);
  9.  
  10.  # Try HKCU first
  11.  $HKEY_CURRENT_USER = $Registry->{"HKEY_CURRENT_USER"};
  12.  $no_warn = $HKEY_CURRENT_USER;
  13.  if ($HKEY_CURRENT_USER->Open($sub_key, $hkey))
  14.  {
  15.    $hkey->GetValues(\%key_values);  
  16.    foreach $temp (sort keys %key_values) {
  17.      if ($temp eq $value) {
  18.        return $key_values{$temp}[2];
  19.      }
  20.    }
  21.    $hkey->Close();
  22.  }


 
Résultat :
Can't call method "Open" on an undefined value
 
 
2ème test :
 

Code :
  1. sub win32_reg_read {
  2.  my $sub_key = shift;
  3.  my $value = shift;
  4.  
  5.  #require Win32::Registry;
  6.  require Win32::TieRegistry;
  7.    
  8.  my ($hkey, %key_values, $temp, $no_warn);
  9.  
  10.  # Try HKCU first
  11.  $HKEY_CURRENT_USER = $Registry->{"HKEY_CURRENT_USER\\"};
  12.  $no_warn = $HKEY_CURRENT_USER;
  13.  if ($HKEY_CURRENT_USER->Open($sub_key, $hkey))
  14.  {
  15.    $hkey->GetValues(\%key_values);  
  16.    foreach $temp (sort keys %key_values) {
  17.      if ($temp eq $value) {
  18.        return $key_values{$temp}[2];
  19.      }
  20.    }
  21.    $hkey->Close();
  22.  }


 
Résultat :
Can't call method "Open" on an undefined value


Message édité par akizan le 02-03-2012 à 13:23:29
Reply

Marsh Posté le 02-03-2012 à 11:47:15    

Il faut aller lire la doc du module: Open ne fonctionne plus du tout pareil.
 

Code :
  1. sub win32_reg_read {
  2.  my $sub_key = shift;
  3.  my $value = shift;
  4.  
  5.  use Win32::TieRegistry;
  6.  
  7.  my $HKEY_CURRENT_USER  = Win32::TieRegistry->new("CUser" );
  8.  if ($HKEY_CURRENT_USER) {
  9.    my $skey = $HKEY_CURRENT_USER->Open($sub_key);
  10.    if ($skey) {
  11.      my %key_values = $skey->GetValue($value);
  12.      foreach (sort keys %key_values) {
  13.         print $_, "\n"; # a toi d'adapter ton code à ce que tu avais dans ta boucle
  14.      }
  15.    }
  16.  }
  17. }
  18.  
  19. # ControlPanel\Current Color Schemes
  20. win32_reg_read("Control Panel\\Current\\", "Color Schemes" );
  21. # -> renvoie Windows Standard


 
A+,


Message édité par gilou le 02-03-2012 à 11:47:38

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 02-03-2012 à 15:33:58    

Merci de ton aide mais je vais pas m'en sortir tout seul...
Du coup j'ai changé Strawberry par ActiveState et y a plus d'erreur dans le code :)
 
Merci à toi en tout cas !!

Reply

Marsh Posté le 02-03-2012 à 15:33:58   

Reply

Marsh Posté le 02-03-2012 à 16:10:54    

Parce qu'il te manquait le module sous strawberry?
Suffisait de l'installer avec CPAN, non?
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 05-03-2012 à 10:43:56    

Arf :(
Je ne savais pas.... il faudra que je regarde comment on fait dans ce cas :)
Merci beaucoup !

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed