PC SOFT

FORUMS PROFESSIONNELS
WINDEVWEBDEV et WINDEV Mobile

Accueil → WINDEV 22 → [WD15] Protection par cle
[WD15] Protection par cle
Débuté par Alain, 19 juin 2010 23:05 - 37 réponses
Posté le 19 juin 2010 - 23:05
Bonjour à tous,

Je suis passé à WD 15 depuis peu.
Sous WD 5.5, pour protéger mes softs j'utilisais la fonction qui permet d'extraire le n°"constructeur" du disque dur du client (9 caractères) avec la fonction.
//Ch1 est une chaine
//Ch1=InformationVolume(fDisqueEnCours()[[1]])

Avec WD15 cela ne fonctionne plus.
Si j'utilise la fonction
//Ch1 est une chaine
//Ch1= fDisqueInfo(fDisqueEnCours(),fdNuméroDeSérie)
cela retourne le n°de 10 caractères relatif au formatage du DD et non au n° de série constructeur.
C'est pas correct car le client doit pouvoir réinstaller le soft autant de fois que nécessaire tant que son disque dur reste le même (même reformaté à plusieurs reprises).

Merci de votre aide.
Alain
Posté le 20 juin 2010 - 11:12
Bonjour

Effecivement en WD 15, la fonction renvoie le n° de partition du disque dur et donc, à chaque formatage, il va changer. Par le passé, en utilisant les fonctions WMI, j'ai pu obtenir le n° constructeur du disque. Le seul problème qui m'a fait abandonner cette voix, c'est que certains constructeurs comme Dell, HP... bloque ou détourne cette information. Après de nombreux tests sur des machines différentes et avec des OS différents, il m'arrivait d'avoir une chaine vide donc sans n°. Ce qui n'était donc pas sûr à 100%.
Sur ce forum, cette question a déjà et fera encore l'objet de pas mal de fil, je pense.
Pour résoudre le problème du formatage et de la clé, je ne vois que la solution de mettre en place une procédure de maintenance en quelque sorte. Le client reçoit sa première clé puis par la suite, après formatage, il refait une demande avec le nouveau n° de série. Autre possibilité, créer une fonction de transfert de licence pour le client qui la met en oeuvre. Inconvénient de cette méthodes : quid si le formatage a déjà eu lieu ? On en revient alors à la 1ère hypothèse.
Reste la carte MAC mais là aussi j'ai constaté que les clients qui utilisent une machine virtuelle sous poste MAC (entre autres car certains n'ont tout simplement pas de crate Ethernet) ne renvoit pas de n° mais une chaine : MAC=Err SendARP. Donc toujours pas de certitude.
La solution d'une seconde demande me parait la plus acceptable mais à condition que le rythme des formatages le soit aussi.
Je suis preneur si quelqu'un trouve une solution fiable à 100% mais c'est pas gagné.
Bonne continuation.
Cordialement
Posté le 20 juin 2010 - 20:44
bonjour,
voici une méthode pour récupérer des infos disque (nom physique,type,numéro de série) avec Windev :
En utilisant WMI avec assemblage DotNet
Pour utiliser cela dans votre projet il vous faut :
1 - Utiliser l'assemblage .NET "System.Management" :
Menu Atelier/.NET/Utiliser Un Assemblage .NET dans ce projet
Dans la fenêtre qui s'ouvre cliquer sur "Lister les assemblages référencés"
Quand la recherche est terminée cocher "Mscorlib" et "System.Management"
2 - Récupérer la collection de procédure pWMI.wdg qui se trouve dans l'exemple complet WD WMI DOTNET
et l'inclure dans votre projet
Rajouter la procédure suivante dans votre collection pWMI.wdg

// Résumé : <indiquez ici ce que fait la procédure>
// Syntaxe :
//RécupèreInfoNumSérieDisque ()
//
// Paramètres :
//Aucun
// Valeur de retour :
// Aucune
// J.P Juin 2010
// Exemple :
// Indiquez ici un exemple d'utilisation.
//
Procedure RécupèreInfoNumSérieDisque()

sChaineRetour est une chaîne
sListeInfoest une chaîne
sUneInformation est une chaîne

sListeInfo = RécupèreContenu("Win32_DiskDrive",gsServeur + "root\CIMV2")

POUR TOUTE CHAINE sUneInformation DE sListeInfo SEPAREE PAR RC+RC

// Récupération des informations
// Récupératon du nom physique du disque
sChaineRetour += "Disque : " + TrouveInformation(sUneInformation,"Name") + RC +...
// Récupération du modèle de disque
"Type : " + TrouveInformation(sUneInformation,"Model") + RC +...
// Récupération du numéro de série
"Numéro de série : " + TrouveInformation(sUneInformation,"SerialNumber") + RC +...
"=====================================================" + RC
FIN
RENVOYER sChaineRetour


il faut adapter cette procédure à ton besoin :
ne récupérer que l'information SerialNumber en fonction du nom physique du disque que tu testes.

Ami Calmant, J.P ;-)
Posté le 20 juin 2010 - 20:45
Bonjour,


Le procédure InformationVolume livrée en son temps dans les exemples de WD5.5 fonctionne parfaitement sous WD15.
il faut simplement prendre la précaution de changer les entiers "courts" et "longs" dans les déclarations et d'inclure en fin de procédure

NomVol = Remplace(NomVol,"FFFF","")

Bon dev
Posté le 20 juin 2010 - 20:45
Bonjour,

Comme vous l'avez bien résumé en fin de votre post, il n'existe pas de solution garantie à 100%, les personnes qui ont un peu travaillé le sujet le savent bien, c'est la seule certitude...
Pour ma part, sachant que je ne diffuse pas mes logiciels à grande échèle et que je souhaite pas "passer" par un système de dongle, finalement payé par le client, j'avais trouvé avec la mise en œuvre de la fonction " InformationVolume(fDisqueEnCours()[[1]]) " le bon degré de sécurité.

Sur le fond, si cette fonction en Wlangage existait sous WD 5.5 elle doit avoir son équivalence stricte sous WD 15.

Merci au modérateur du présent forum, qui lit tous les posts avant de les diffuser, de bien vouloir relayer la question aux développeurs de PCSOFT afin qu'ils apportent une réponse à cette question récurrente depuis longtemps sur les divers forums du site.
Je ne voudrais pas me sentir bloqué à cause de cette fonction et devoir continuer à développer sous WD 5.5
Si d'autre personnes ont des solutions équivalentes, tout le monde est preneur.

Merci
Alain
Posté le 21 juin 2010 - 08:59
Bonjour,

dans la procédure décrite précédemment, il est préférable d'utiliser Win32_PhysicalMedia que Win32_DiskDrive car le numéro de série n'est pas formaté avec Win32_DiskDrive
la procédure devient alors :
// Résumé : <indiquez ici ce que fait la procédure>
// Syntaxe :
//RécupèreInfoNumSérieDisque ()
//
// Paramètres :
//Aucun
// Valeur de retour :
// Aucune
//
// Exemple :
// Indiquez ici un exemple d'utilisation.
// J.P Juin 2010
Procedure RécupèreInfoNumSérieDisque()

sChaineRetour est une chaîne
sListeInfoest une chaîne
sUneInformation est une chaîne


sListeInfo = RécupèreContenu("Win32_PhysicalMedia",gsServeur + "root\CIMV2")

POUR TOUTE CHAINE sUneInformation DE sListeInfo SEPAREE PAR RC+RC

// Récupération des informations
// Tag nom physique du média (\\.\PHYSICALDRIVE0 est en général le 1er disque dur -> A confirmer)
sChaineRetour += "Disque Physique : " + TrouveInformation(sUneInformation,"Tag") + RC +...
// Récupération du numéro de série si il est présent
"Numéro de série : " + TrouveInformation(sUneInformation,"SerialNumber") + RC +...
"=====================================================" + RC
FIN
RENVOYER sChaineRetour


Limitations :
Il faut que le framework Dotnet soit installé sur la station où s'exécute le code.
Parfois aucun numéro de série n'est renvoyé. Il faudra alors se rabattre sur autre chose, par exemple l'adresse MAC de la carte réseau.

Ami calmant, J.P ;-)
Posté le 21 juin 2010 - 13:19
Bonjour Alain,

Comme tu le disais :

"... j'avais trouvé avec la mise en œuvre de la fonction " InformationVolume(fDisqueEnCours()[[1]]) " le bon degré de sécurité.

Sur le fond, si cette fonction en Wlangage existait sous WD 5.5 elle doit avoir son équivalence stricte sous WD 15.
"

En fait la bonne question est bien "Si cette fonction existait sous WD5.5" car (et je viens bien sûr de le vérifier sur ma version de Windev 5.5 encore opétrationnelle) cette fonction n'EXISTE PAS en natif.
Il est donc probable que dans tes procédures tu aies codé une telle fonction à partir d'autre natives ou API.
Regarde un ancien projet utilisant cette protection et tu devrais retrouver le code initiale de ta protection.

Tiens nous au courant.

A+
--
Francis MOREL
http://www.SoftProtect.fr
Posté le 21 juin 2010 - 13:26
Bonjour

Je suis tout à fait d'accord mais comme je l'ai dit, et je trouve que cela se systèmatise de plus en plus sans raison même je pense, les constructeurs comme Dell, HP et même Toshiba veulent personnaliser leur OS. Le n° constructeur du disque doit alors être une donnée hautement statégique car il le bloque. Pour la carte MAC, on ne peut pas toujours avoir son n°.
Ce qui fait qu'un système bati sur ces n° ne sera, dès le départ, ni sûr et ni complet car ne répondant pas au critère d'universalité que nous voulons tous.

Réflexion/suggestion :
Je lance une idée qui vaut ce qu'elle vaut. Seuls de nombreux tests sur des machines différentes avec des OS différents, nous permettraient de dégager une statistique sur le renvoi d'un n° constructeur ou carte MAC. On pourrait même identifier, modèle par modèle de leur production, les constructeurs qui brident
leurs machines et pourquoi pas trouver un matériel avec n° unique, même si c'est à leur manière.
Plus la statistique se rapprochera du 100 et plus le système serait intéressant à mettre en place (sans aucun surcoût pour le client et l'éditeur).
Il faudrait simplement mettre à disposition des personnes intéressées le code Windev pour lire ces n° (moi j'ai abandonné l'idée de ce n° constructeur et je n'ai donc pas un source tout prêt). Ensuite il faudrait mettre en place le protocole de test : définir un format pour le recueil des résultats :
Date, caractéristiques de la machine, de l'OS, machine virtuelle ou non, dédiée internet ou non, réseau ou non, n° constructeur....
En peu de temps, si beaucoup sont intéressés, on obtiendrait facilement la réponse aux questions posées, libre ensuite à chacun de mettre en place son système de licence.
C'est une idée comme une autre il faut "Just do it".

Cordialement à tous
Posté le 22 juin 2010 - 02:39
Bonjour Francis et merci pour ton aide.

Je vais apporter quelques précisions à mon post initial.

1) La procédure " InformationVolume(fDisqueEnCours()[[1]]) " provient d'un exemple livré avec Wd 5.5 (version 5.53Yb interne 01-55057) qui s'appelle WD5CODE et appartenant à la fenêtre nommée Coddd.wdw.
Je ne voudrais pas rendre ce post indigeste, mais bon pour une meilleure compréhension, je colle ci-dessous la procédure en question (celle d'origine avant migration de WD 5.5 vers 7.5 vers 15).

2) Après essais, je fais le constat suivant:
Si je test la proc sous WD15 et Windows Vista 32 bit = OK cela fonctionne très bien.
Si je test la proc sous WD15 et Windows Seven 64 bit = NON cela ne fonctionne plus (sans bug, n'affiche plus le n° du DD).

Alors questions:
-est ce un problème de code ?
J'ai commencé à regarder, mais c'est du lourd....
-est ce la DLL "VOLINF" qui est appelée dans le procédure et qui n'est pas/plus compatible avec du 64 bit ?
Nb: cette DLL n'est pas présente dans Seven c'est une DLL d'origine WD très certainement.

A la lumière de ces infos supplémentaires, est t'il possible que PC SOFT se penche sur ce code et modifie cette procédure qui concerne des utilisateurs actuel Windows 64bit qui ont fait le pas vers WD15 et futur qui vont le faire mais qui ne savent pas encore que cela ne fonctionne plus.

Bien sur, les exemples sont sensés rester "que" des exemples, mais là, vu la difficulté de mise en œuvre du code et le nombre de personnes qui utilise cette fonction, je pense qu'il serait bien que PC SOFT nous "dépatouille".

Merci d'avance aux bonnes volontés de proposer, soit les modificatifs nécessaires testées au fonctionnement du présent code soit à la présentation d'une autre fonction équivalente éprouvée sous WD15 et Windows 32 et 64 bit.

Bon dev
Alain

//********************************************************************************
//********************************************************************************
fonction InformationVolume(asLecteur)

RootPathName est un chaine ASciiz sur 255
GetDriveType est un entier long
NumVol est une chaine
glpBuff est un entier long // Handle de la structure 16 bit
aiLecteur est un entier
gsWindowsVer est une chaine // Version de WIndows
gHndlLib est un entier long // Handle de DLL (pour le 16 bits)

// Variables de retour de GetVolumeInformationA
VolumeNameBuffer est une chaine asciiz sur 255
VolumeNameSize est un entier long = 255
VolumeSerialNumber est un entier long
MaxComponentLength est un entier long
FilesystemFlag est une entier long
FileSystemNameBuffer est une chaine asciiz sur 255
FileSystemNameSize est une entier long = 255

// Structure de retour de PrendVolInfo (16 bits)
BOOTSec est composée de
Jump est un tableau de 3 entier court
OemName est un chaine fixe sur 8
BytePerSec est un entier sans signe
SecPerCLus est entier court
ResSect est un entier sans signe
FAT est un entier court
DirEntr est un entier sans signe
Secteur est un entier sans signe
Media est un entier court
FATSec est un entier sans signe
SecPerTr est un entier sans signe
Head est un entier sans signe
HiddenSec est un entier long
HugeSec est un entier long
DriveNum est un entier court
Reserved est un entier court
BootSig est un entier court
VolumeID est un entier long
VolLab est une chaine fixe de 11
FileSysT est une chaine fixe de 8
Fin

gsWindowsVer = versionWindows() // Récupère version de Windows (gain de temps)

si gsWindowsVer <> "32" Alors
gHndlLib = ChargeDLL("VOLINF.DLL")
si gHndlLib = 0 alors
//Erreur : La Librairie n'est pas chargée
NumVol=""
FIN
sinon
gHndlLib = 1
Fin


si gHndlLib <>0 alors //Mode 32 bits ou 16 bits + librairie chargé
//N° correspondant au lecteur
aiLecteur=asc(asLecteur)-asc("A")

si gsWindowsVer <> "32" alors
glpBuff = &BOOTSec // Récupération de l'adresse de la structure
fin

// Récupération du numéro de série
PartieHaute est un entier sans signe
PartieBasse est un entier sans signe
ResultatFct est un booleen
RootPathName = sansespace(asLecteur) + ":\"

si gsWindowsVer = "32" alors
GetDriveType = AppelDll32("KERNEL32", "GetDriveTypeA", RootPathName)
Sinon
GetDriveType = AppelDLLLong("KERNEL", "GetDriveType", aiLEcteur)
Fin

Si GetDriveType > 0 Alors // Problème d'accés au lecteur
// Récupération des informations du disque
Si gsWindowsVer = "32" alors
ResultatFct = Appeldll32("KERNEL32", "GetVolumeInformationA", RootPathName, &VolumeNameBuffer, VolumeNameSize, ...
&VolumeSerialNumber, &MaxComponentLength, &FileSystemFlag, &FileSystemNameBuffer, ...
FileSystemNameSize)
Sinon
ResultatFct = AppelDLL("VOLINF", "PrendInfoVol", aiLecteur, glpBuff)
Fin

// Test de le résultat de la fonction d'interrrongation
Si ResultatFct Alors
si gsWindowsVer <> "32" Alors
VolumeSerialNumber = BOOTSec.VolumeID
Fin
PArtieBasse = loWord(VolumeSerialNumber)
PartieHaute = HiWord(VolumeSerialNumber)
NumVol=VersChaine(PartieHaute,"4X") + "-" + Verschaine(PartieBasse,"4X")
sinon
//Cas de l'appication en 16 bits, sur fat autre que FAT16
info("Le système de protection de cette application ne permet pas un fonctionnement correct dans ce mode d'exécution.",...
"La version 16 bits ne fonctionne que sur les FAT16.", ...
"Demander une version commerciale à votre revendeur.")

NumVol="Numéro de disque dur non obtenu"
Demande=Faux
Fin
sinon
info("Le système de protection de cette application ne permet pas un fonctionnement correct dans ce mode d'exécution.",...
"Problème d'accès au lecteur",...
"Demander une version commerciale à votre revendeur.")
NumVol="Numéro de disque dur non obtenu"
Demande=Faux
fin
si gsWindowsVer <> "32" alors
// Décharge la librairie
DechargeDLL(gHndlLib)
Fin
fin

renvoyer NumVol
Posté le 22 juin 2010 - 09:07
bonjour Alain,

voici le code modifié qui marche chez moi ( Windows 7 64 bits)
j'ai enlevé tout ce qui concerne le 16 bits ce n'est plus d'actualité (WIN98)
Procedure InformationVolume(asLecteur)
//********************************************************************************
//********************************************************************************
Demande est un booléen
RootPathName est un chaîne ASCIIZ sur 255
GetDriveType est un entier long
NumVol est une chaîne
aiLecteur est un entier
gsWindowsVer est une chaîne // Version de WIndows


// Variables de retour de GetVolumeInformationA
VolumeNameBuffer est une chaîne ASCIIZ sur 255
VolumeNameSize est un entier long = 255
VolumeSerialNumber est un entier long
MaxComponentLength est un entier long
FilesystemFlag est une entier long
FileSystemNameBuffer est une chaîne ASCIIZ sur 255
FileSystemNameSize est une entier long = 255



gsWindowsVer = VersionWindows() // Récupère version de Windows (gain de temps)



//N° correspondant au lecteur
aiLecteur=Asc(asLecteur)-Asc("A")


// Récupération du numéro de série
PartieHaute est un entier sans signe sur 2 octets
PartieBasse est un entier sans signe sur 2 octets
ResultatFct est un booléen
RootPathName = SansEspace(asLecteur) + ":\"

GetDriveType = API("KERNEL32", "GetDriveTypeA", RootPathName)


SI GetDriveType > 0 ALORS // Problème d'accés au lecteur
// Récupération des informations du disque

ResultatFct = AppelDLL32("KERNEL32", "GetVolumeInformationA", RootPathName, &VolumeNameBuffer, VolumeNameSize, ...
&VolumeSerialNumber, &MaxComponentLength, &FilesystemFlag, &FileSystemNameBuffer, ...
FileSystemNameSize)


// Test de le résultat de la fonction d'interrogation
SI ResultatFct ALORS

PartieBasse = LoWord(VolumeSerialNumber)
PartieHaute = HiWord(VolumeSerialNumber)
NumVol=NumériqueVersChaîne(PartieHaute,"4X") + "-" + NumériqueVersChaîne(PartieBasse,"4X")


FIN
SINON
Info("Le système de protection de cette application ne permet pas un fonctionnement correct dans ce mode d'exécution.",...
"Problème d'accès au lecteur",...
"Demander une version commerciale à votre revendeur.")
NumVol="Numéro de disque dur non obtenu"
Demande=Faux
FIN



RENVOYER NumVol


Mais au risque de te décevoir c'est le même résultat que la fonction fDisqueInfo(fDisqueEnCours(),fdNuméroDeSérie) c'est à dire le numéro de volume celui qui est généré au formatage du disque.
Résultat est une chaîne
Volinf est un entier
PartieHaute est un entier sans signe sur 2 octets
PartieBasse est un entier sans signe sur 2 octets

Volinf = fDisqueInfo(fDisqueEnCours(),fdNuméroDeSérie)
PartieBasse = LoWord(Volinf)
PartieHaute = HiWord(Volinf)
Résultat = NumériqueVersChaîne(PartieHaute,"4X") + "-" + NumériqueVersChaîne(PartieBasse,"4X")


Ami calmant, J.P ;-)
Posté le 22 juin 2010 - 09:07
Pour tous les déçus de mon message précédent, voici une procédure qui utilise WMI avec assemblage DotNet, récupérant des infos pour générer ou contrôler un numéro de licence.

// Résumé : Récupérer des informations système pour générer ou contrôler un numéro de licence
// Cette procédure utilise la collection pWMI et à incorporer dans celle-ci
// Syntaxe :
//RécupèreInfosLicence ()
//
// Paramètres :
//Aucun
// Valeur de retour :
// Aucune
//
//
// Pensé par Jurassic.Pork Juin 2010
//
Procedure RécupèreInfosLicence()
InfoLicence est une structure
NumSérieDisque est une chaîne
NumVolDisque est une chaîne
NumMacAdresse est une chaîne
NumSérieCarteMère est une chaîne
NumSérieBios est une chaîne
FIN

sUneInformation est une chaîne

MonInfoLicence est une InfoLicence

// Récupération du numéro de série du 1er disque
sUneInformation = RécupèreContenu("Win32_PhysicalMedia",gsServeur + "root\CIMV2", "Tag LIKE '%PHYSICALDRIVE0'")
SI sUneInformation <> "" ALORS
MonInfoLicence.NumSérieDisque = TrouveInformation(sUneInformation,"SerialNumber")
SINON
MonInfoLicence.NumSérieDisque = "INVALIDE"
FIN

// Récupération du numéro de volume du disque C:
sUneInformation = RécupèreContenu("Win32_LogicalDisk",gsServeur + "root\CIMV2", "DeviceID='C:'")
SI sUneInformation <> "" ALORS
MonInfoLicence.NumVolDisque = TrouveInformation(sUneInformation,"VolumeSerialNumber")
SINON
MonInfoLicence.NumSérieDisque = "INVALIDE"
FIN

// Récupération de l'adresse MAC du premier adaptateur réseau valide
sUneInformation = RécupèreContenu("Win32_NetworkAdapter",gsServeur + "root\CIMV2", "PhysicalAdapter=True")
SI sUneInformation <> "" ALORS
MonInfoLicence.NumMacAdresse = TrouveInformation(sUneInformation,"MACAddress")
SINON
MonInfoLicence.NumMacAdresse = "INVALIDE"
FIN

// Récupération du numéro de série de carte mère
sUneInformation = RécupèreContenu("Win32_BaseBoard",gsServeur + "root\CIMV2")
SI sUneInformation <> "" ALORS
MonInfoLicence.NumSérieCarteMère = TrouveInformation(sUneInformation,"SerialNumber")
SINON
MonInfoLicence.NumSérieCarteMère = "INVALIDE"
FIN

// Récupération du numéro de série du BIOS
sUneInformation = RécupèreContenu("Win32_BIOS",gsServeur + "root\CIMV2")
SI sUneInformation <> "" ALORS
MonInfoLicence.NumSérieBios = TrouveInformation(sUneInformation,"SerialNumber")
SINON
MonInfoLicence.NumSérieBios = "INVALIDE"
FIN

// A vous de jouer pour générer ou vérifier la clé de licence avec les infos les plus justes.


Pour utiliser cela dans votre projet il vous faut :
1 - Utiliser l'assemblage .NET "System.Management" :
Menu Atelier/.NET/Utiliser Un Assemblage .NET dans ce projet
Dans la fenêtre qui s'ouvre cliquer sur "Lister les assemblages référencés"
Quand la recherche est terminée cocher "Mscorlib" et "System.Management"
2 - Récupérer la collection de procédure pWMI.wdg qui se trouve dans l'exemple complet WD WMI DOTNET
et l'inclure dans votre projet
Rajouter la procédure RécupèreInfosLicence dans votre collection pWMI.wdg

Contrainte : il faut que le Framework dotnet soit installer sur la station qui utilisera cette procédure.

Ami calmant, J.P ;-)
Posté le 22 juin 2010 - 12:13
Bonjour Jurassic Pork,

Grâce à tes modifications de la procédure, cela fonctionne maintenant comme avant mais pour du 64bit.

Mais effectivement quelque soit la méthode utilisée (sous Windows Seven 64 bit et WD15):

par la procédure " InformationVolume(fDisqueEnCours()[[1]])" de l'exemple WD5CODE

ou par la fonction Wd:
//***********************************************************
Résultat est une chaîne
Volinf est un entier
PartieHaute est un entier sans signe sur 2 octets
PartieBasse est un entier sans signe sur 2 octets
Volinf = fDisqueInfo(fDisqueEnCours(),fdNuméroDeSérie)
PartieBasse = LoWord(Volinf)
PartieHaute = HiWord(Volinf)
Résultat = NumériqueVersChaîne(PartieHaute,"4X") + "-" + NumériqueVersChaîne(PartieBasse,"4X")
//************************************************************

On obtient strictement la même chaine alphanumérique de 9 caractères.

Conclusion:
Tu as raison, je suis déçu, car c'est bien le n° logique attribué après le formatage qui est extrait par la procédure " InformationVolume(fDisqueEnCours()[[1]])" de l'exemple WD5CODE que je pensais être le N° physique et que j'utilisais comme tel, sans le savoir.
Dans l'exemple WD5CODE cela n'est pas précisé, mais bon c'était qu'un exemple....

Mais alors, ce N° de DD ne peut pas être extrait ? n'y a t'il pas une personne qui aurait la solution ?

Par contre, je persiste, je pense qu'il serait bien que PCSOFT nous aide un peu à extraire ce n° de DD.
A moins que cela se soit impossible ou pas sure à la gestion commerciale de la protection logiciel mais qu'il nous le précise SVP.

J'ai posé la question le 19/06/10 au service technique PCSOFT.... j'attends.

Bon dev à tous et merci encore à toi Jurassic Pork
Alain



Jurassic Pork a écrit dans le message de news <557e96266ab0dcfa66a8583bfc8cb8d1@news.pcsoft> :
bonjour Alain,

voici le code modifié qui marche chez moi ( Windows 7 64 bits)
j'ai enlevé tout ce qui concerne le 16 bits ce n'est plus d'actualité (WIN98)
[code]
PROCEDURE InformationVolume(asLecteur)

Mais au risque de te décevoir c'est le même résultat que la fonction fDisqueInfo(fDisqueEnCours(),fdNuméroDeSérie) c'est à dire le numéro de volume celui qui est généré au formatage du disque.


> Ami calmant, J.P ;-)
Posté le 22 juin 2010 - 12:30
Dans son message précédent, Jurassic Pork a écrit :



Pour tous les déçus de mon message précédent, voici une procédure qui utilise
WMI avec assemblage DotNet, récupérant des infos pour générer ou contrôler un
numéro de licence.


sans assemblage .NET à tester bien sûr sur l'OS désirer :

CONSTANTE
SMART_ENABLE_SMART_OPERATIONS = 0xD8
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
FILE_SHARE_READ = 0x1
FILE_SHARE_WRITE = 0x2
OPEN_EXISTING = 0x3
SMART_CYL_LOW = 0x4F
SMART_CYL_HI = 0xC2
IDE_EXECUTE_SMART_FUNCTION = 0xB0
DFP_GET_VERSION = 0x74080
DFP_SEND_DRIVE_COMMAND = 0x7C084
DFP_RECEIVE_DRIVE_DATA = 0x7C088
IDE_ID_FUNCTION = 0XEC
IDENTIFY_BUFFER_SIZE = 512
OUTPUT_DATA_SIZE = IDENTIFY_BUFFER_SIZE + 16
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = 0x560000
FIN

STIDSector est une structure
nGenConfig est un entier SUR 2 octets
nnNumCyls est un entier SUR 2 octets
nReserved est un entier SUR 2 octets
nNumHeads est un entier SUR 2 octets
nBytesPerTrack est un entier SUR 2 octets
nBytesPerSector est un entier SUR 2 octets
nSectorsPerTrack est un entier SUR 2 octets
sfVendorUnique est une chaîne fixe SUR 6
sfSerialNumber est une chaîne fixe SUR 20
nBufferType est un entier SUR 2 octets
nBufferSize est un entier SUR 2 octets
nECCSize est un entier SUR 2 octets
sfFirmwareRev est une chaîne fixe SUR 8
sfModelNumber est une chaîne fixe SUR 40
nMoreVendorUnique est un entier SUR 2 octets
nDoubleWordIO est un entier SUR 2 octets
nCapabilities est un entier SUR 2 octets
nReserved1 est un entier SUR 2 octets
nPIOTiming est un entier SUR 2 octets
nDMATiming est un entier SUR 2 octets
nBS est un entier SUR 2 octets
nNumCurrentCyls est un entier SUR 2 octets
nNumCurrentHeads est un entier SUR 2 octets
nNumCurrentSectorsPerTrack est un entier SUR 2 octets
nCurrentSectorCapacity est un entier SUR 4 octets
nMultSectorStuff est un entier SUR 2 octets
nTotalAddressableSectors est un entier SUR 4 octets
nSingleWordDMA est un entier SUR 2 octets
nMultiWordDMA est un entier SUR 2 octets
sfReserved est une chaîne fixe SUR 128
FIN

STAttr_Data est une structure
nAttrIDest est un entier sans signe SUR 1 octet
sAttrName est une chaîne
nAttrValueest est un entier sans signe SUR 1 octet
nThresholdValueest est un entier sans signe SUR 1 octet
nWorstValueest est un entier sans signe SUR 1 octet
nStatusFlags est un entier sans signe SUR 1 octet
FIN

STDrive_Info est une structure
nDriveType est un entier sans signe SUR 1 octet
sSerialNumber est une chaîne
sModel est une chaîne
sFirmWare est une chaîne
nCilinders est un entier SUR 4 octets
nHeads est un entier SUR 4 octets
nSecPerTrack est un entier SUR 4 octets
nBytesPerSector est un entier SUR 4 octets
nBytesperTrack est un entier SUR 4 octets
nNumAttributes est un entier sans signe SUR 1 octet
tabAttributes est un tableau dynamique de 0 STAttr_Data
FIN

STIDERegs est une structure
nFeaturesReg est un entier sans signe SUR 1 octet
nSectorCountReg est un entier sans signe SUR 1 octet
nSectorNumberReg est un entier sans signe SUR 1 octet
nCylLowReg est un entier sans signe SUR 1 octet
nCylHighReg est un entier sans signe SUR 1 octet
nDriveHeadReg est un entier sans signe SUR 1 octet
nCommandReg est un entier sans signe SUR 1 octet
nReserved est un entier sans signe SUR 1 octet
FIN

STSendCmdInParams est une structure
nBufferSize est un entier SUR 4 octets
stIrDriveRegs est un STIDERegs
nDriveNumber est un entier sans signe SUR 1 octet
tabReserved est un tableau fixe de 3 entiers sans signe SUR 1 octet
tabDwReserved est un tableau fixe de 4 entiers sans signe SUR 4 octets
nBuffer est un entier //est un tableau dynamique de 0 entier sans
signe sur 1 octet
FIN

STDriverStatus est une structure
nDriverError est un entier sans signe SUR 1 octet
nIDEStatus est un entier sans signe SUR 1 octet
tabReserved est un tableau de 2 entiers sans signe SUR 1 octet
tabDwReserved est un tableau de 2 entiers SUR 4 octets
FIN

STSendCmdOutParams est une structure
nBufferSize est un entier SUR 4 octets
DRIVERSTATUS est un STDriverStatus
tabBuffer est un tableau dynamique de 0 entier sans signe SUR 1 octet
FIN

STDisk_Extent est une structure
nDiskNumber est un entier SUR 4 octets
nReserved est un entier SUR 4 octets sans signe
nStartingOffset est un entier SUR 8 octets
nExtentLength est un entier SUR 8 octets
FIN

STVolume_Disk_Extents est une structure
nNumberOfDiskExtents est un entier SUR 4 octets
nReserved est un entier SUR 4 octets sans signe
tabExtents est un tableau dynamique de 0 STDisk_Extent
FIN

PROCEDURE GetDriveInfo(cLettreLecteur est un caractère)

nHandleDrive est un entier sans signe
stDI est un STDrive_Info
nDriveNumber est un entier
bRetour est un booléen
nBytesReturned est un entier sans signe SUR 4 octets
sfArrOut est une chaîne fixe SUR 528
stVDE est un STVolume_Disk_Extents
nOffset est un entier

nHandleDrive =
API("kernel32","CreateFileA","\\.\"+cLettreLecteur+":",OUBinaire(GENERIC_READ,GENERIC_WRITE),OUBinaire(FILE_SHARE_READ,FILE_SHARE_WRITE),0,OPEN_EXISTING,0,0)
SI nHandleDrive <> -1 ALORS
bRetour =
API("kernel32","DeviceIoControl",nHandleDrive,IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,Null,0,&sfArrOut,56,&nBytesReturned,0)
Transfert(&stVDE:nNumberOfDiskExtents,&sfArrOut,4)
Transfert(&stVDE:nReserved,&sfArrOut,4)
nOffset = 8
TANTQUE nOffset < nBytesReturned
TableauAjoute(stVDE:tabExtents)
Transfert(&stVDE:tabExtents[Dimension(stVDE:tabExtents)]:nDiskNumber,&sfArrOut+nOffset,4)
Transfert(&stVDE:tabExtents[Dimension(stVDE:tabExtents)]:nReserved,&sfArrOut+nOffset+4,4)
Transfert(&stVDE:tabExtents[Dimension(stVDE:tabExtents)]:nStartingOffset,&sfArrOut+nOffset+8,8)
Transfert(&stVDE:tabExtents[Dimension(stVDE:tabExtents)]:nExtentLength,&sfArrOut+nOffset+16,8)
nOffset+= 24
FIN
SI Dimension(stVDE:tabExtents) > 0 ALORS
nDriveNumber = stVDE:tabExtents[1]:nDiskNumber
FIN
SmartClose(nHandleDrive)
FIN

nHandleDrive = SmartOpen(nDriveNumber)
SI nHandleDrive <> -1 ALORS
// si SmartGetVersion(nHandleDrive) alors
stDI:nDriveType = 0
stDI:nNumAttributes = 0
Dimension(stDI:tabAttributes,0)
stDI:nDriveType = 1

SI SmartCheckEnabled(nHandleDrive,nDriveNumber) ALORS
SI IdentifyDrive(nHandleDrive,IDE_ID_FUNCTION,nDriveNumber,stDI)
ALORS

FIN
FIN
// fin
SmartClose(nHandleDrive)
FIN

RENVOYER(stDI)

// ***** appel de la méthode
stInfo est un STDrive_Info

stInfo = GetDriveInfo("C")
Trace(stInfo:sSerialNumber)
//************************************************************************************
PROCEDURE SmartOpen(nDriveNumber)

nHandle est un entier

nHandle =
API("kernel32","CreateFileA","\\.\PhysicalDrive"+nDriveNumber,OUBinaire(GENERIC_READ,GENERIC_WRITE),OUBinaire(FILE_SHARE_READ,FILE_SHARE_WRITE),0,OPEN_EXISTING,0,0)

RENVOYER(nHandle)
//*****************************************************************
PROCEDURE SmartCheckEnabled(nHandleDrive est un entier sans signe,
nDriveNumber est un entier)

bRetour est un booléen
stSCIP est un STSendCmdInParams
nAdrSCIP est un entier
nBytesReturned est un entier sans signe SUR 4 octets
sfArrOut est une chaîne fixe SUR 528

stSCIP:nBufferSize = 0
stSCIP:stIrDriveRegs:nFeaturesReg = SMART_ENABLE_SMART_OPERATIONS
stSCIP:stIrDriveRegs:nSectorCountReg = 1
stSCIP:stIrDriveRegs:nSectorNumberReg = 1
stSCIP:stIrDriveRegs:nCylLowReg = SMART_CYL_LOW
stSCIP:stIrDriveRegs:nCylHighReg = SMART_CYL_HI

stSCIP:stIrDriveRegs:nDriveHeadReg = 0xA0
SI PAS IsWinNT4Plus() ALORS
stSCIP:stIrDriveRegs:nDriveHeadReg =
OUBinaire(stSCIP:stIrDriveRegs:nDriveHeadReg,(ETBinaire(nDriveNumber,1)
* 16))
FIN
stSCIP:stIrDriveRegs:nCommandReg = IDE_EXECUTE_SMART_FUNCTION
stSCIP:nDriveNumber = nDriveNumber

nAdrSCIP = &stSCIP
bRetour =
API("kernel32","DeviceIoControl",nHandleDrive,DFP_SEND_DRIVE_COMMAND,nAdrSCIP,32,&sfArrOut,16,&nBytesReturned,0)

RENVOYER(bRetour)
//************************************************************************
PROCEDURE IdentifyDrive(nHandleDrive est un entier sans signe, nIDCmd
est un entier sans signe SUR 1 octet, nDriveNumber est un entier, stDI
est un STDrive_Info)

bRetour est un booléen
stSCIP est un STSendCmdInParams
nAdrSCIP est un entier
stSec est un STIDSector
sfArrOut est une chaîne fixe SUR 528
nBytesReturned est un entier sans signe SUR 4 octets

stSCIP:nBufferSize = IDENTIFY_BUFFER_SIZE
stSCIP:nDriveNumber = nDriveNumber
stSCIP:stIrDriveRegs:nFeaturesReg = 0
stSCIP:stIrDriveRegs:nSectorCountReg = 1
stSCIP:stIrDriveRegs:nSectorNumberReg = 1
stSCIP:stIrDriveRegs:nCylLowReg = 0
stSCIP:stIrDriveRegs:nCylHighReg = 0
stSCIP:stIrDriveRegs:nDriveHeadReg = 0xA0
SI PAS IsWinNT4Plus() ALORS
stSCIP:stIrDriveRegs:nDriveHeadReg =
OUBinaire(stSCIP:stIrDriveRegs:nDriveHeadReg,(ETBinaire(nDriveNumber,1)
* 16))
FIN
stSCIP:stIrDriveRegs:nCommandReg = nIDCmd

nAdrSCIP = &stSCIP
SI
API("kernel32","DeviceIoControl",nHandleDrive,DFP_RECEIVE_DRIVE_DATA,nAdrSCIP,32,&sfArrOut,OUTPUT_DATA_SIZE,&nBytesReturned,0)
ALORS
Transfert(&stSec,(&sfArrOut+16),256)
stDI:sModel = SansEspace(SwapString(stSec:sfModelNumber))
stDI:sSerialNumber = SansEspace(SwapString(stSec:sfSerialNumber))
RENVOYER(Vrai)
FIN

RENVOYER(Faux)
//*****************************************************************************************
ROCEDURE SmartClose(nHandleDrive est un entier sans signe)

API("kernel32","CloseHandle",nHandleDrive)
nHandleDrive = 0
//************************************************************************************
PROCEDURE IsWinNT4Plus()

RENVOYER(Val(SysVersionWindows(sysVersionNuméro)) >= 4 ET
SysVersionWindows(sysVersionPlateForme) = "NT")
//********************************************************************************
PROCEDURE SwapString(sChaine est une chaîne)

sSwap est une chaîne
nIndex est un entier

POUR nIndex = 1 _A_ Taille(sChaine) PAS 2
sSwap+= sChaine[[nIndex+1]]+sChaine[[nIndex]]
FIN

RENVOYER(sSwap)
//*********************************************************************************
PROCEDURE SmartGetVersion(nHandleDrive est un entier)

GETVERSIONOUTPARAMS est une structure
bVersion est un entier sans signe SUR 1 octet
bRevision est un entier sans signe SUR 1 octet
bReserved est un entier sans signe SUR 1 octet
bIDEDeviceMap est un entier sans signe SUR 1 octet
fCapabilities est un entier sans signe SUR 4 octets
dwReserved est un tableau de 4 entiers sans signe SUR 4 octets
FIN

GOV est un GETVERSIONOUTPARAMS
cbByteReturned est un entier sans signe SUR 4 octets
bRetour est un booléen
sfArrOut est une chaîne fixe SUR 528

bRetour =
API("kernel32","DeviceIoControl",nHandleDrive,DFP_GET_VERSION,Null,0,&sfArrOut,24,&cbByteReturned,0)

RENVOYER(bRetour)

--
Cordialement JeAn-PhI
Posté le 24 juin 2010 - 08:58
bonjour,
merci Jean-Phi pour ton code, il fonctionne chez moi avec windows 7.

exemple d' utilisation (avec en plus le relevé de l'adresse MAC de la carte réseau) :
MesstDI est un STDrive_Info
MesstDI = GetDriveInfo("c")
Memo += "Numéro de série disque C : " + MesstDI.sSerialNumber + RC
Memo += "Modèle : " + MesstDI.sModel + RC
Memo += "Adresse MAC : " + NetAdresseMAC()


Si les développeurs de PCSOFT pouvaient intégrer ton code et modifier la fonction fdisqueInfo se serait parfait. Voilà ce que ça pourrait donner :
// Numéro de série du disque
Résultat= fDisqueInfo("C:", fdNuméroDeSérieConstructeur)


Ami calmant, J.P ;-)
Posté le 24 juin 2010 - 16:55
Salut Jurassic,

J'ai une question sur NetAdresse() que j'ai abandonné suite à quelques soucis:

Pourrais tu me confirmer?

Suite au reformatage d'un disque cette fonction me renvoyait des adresse mac differentes dans le cas d'un pc possédant 2 cartes réseaux et ou 1 carte wifi (j'ai supposé qu'il prenait une carte aléatoirement et n'avait pas trouvé de solution)

Cela serait certainement plus interessant car je trouve cette fonction la plus simple et pratique pour placer une protection logicielle

Merci d'avance
Posté le 24 juin 2010 - 20:17
bonjour The Duke,

il est vrai que l'ordre des cartes réseaux n'est pas garanti après une réinstallation complète. Pour éviter cela il faut essayer de balayer toutes les cartes réseau et regarder si l'une d'entre elles à la bonne adresse MAC comme dans le code suivant :
CarteRéseauOK est un booléen = Faux
POUR x = 0 A 5 // 5 peut être modifié nb max de cartes réseau possibles
// AdresseMacLicence représente l'adresse MAC prise en compte pour la licence
SI NetAdresseMAC(x) = AdresseMacLicence ALORS CarteRéseauOK = Vrai
FIN

NetAdresseMAC apparemment ne renvoie rien quand il ne trouve pas la carte réseau d'ordre x.

AMi calmant, J.P ;-)
Posté le 26 juin 2010 - 09:49
Bonsoir

Il semble dommage que personne n'ait lu mes précédents post.
Je disposais dune routine pour récupérer le n° constructeur du disque dur mais après test sur différentes machaines et différents OS, je me suis apercçu que certains constructeurs comme Dell, HP et Toshiba maintenant ont personnalisé et bridé l'OS livré avec leur produit. La fonction ne retourne rien et le n° constructeur est vide.
En conclusion, vous n'aurez pas de certitude à 100% et ensuite il faudra bien gérer ce cas de figure : aucun n° retourné.
Maintenant, vous pouvez continuer vos test en ignorant cette remarque.

Cordialement
Posté le 26 juin 2010 - 22:33
Merci Jurassic pour cette confirmation, malheuresement cette solution ne m'arrange guère la simple raison suivante:

Le client teste mon produit. Après période de test il décide de l'acheter et m'envoie donc un code que nous appelerons "Code Demande" crypté sur l'adresse Mac choisi.
Je renvoie un code "Code Deblocage" au client qui l'inscrit sur son bloc note.

A la prochaine installation si le rang a changé, catastrophe....
Membre enregistré
4 messages
Posté le 31 janvier 2011 - 13:13
Salut tout le monde,
je reviens à propos du post de Jean Phi et du code qu'il a posté après quelques mois déjà car c'est un sujet qui m'intéresse beaucoup
Je suis en train de développer une protection avec des clefs USB
J'ai donc besoin de récupérer le numéro de série de la clé
or le code proposé fonctionne apparemment uniquement avec des disques durs et ne me renvoie rien pour une clé USB
Je suis incapable de modifier ce code tout seul malheureusement, ça me dépasse totalement ces appels API
Est ce que quelqu'un pourrais m'aider à ce sujet?
Merci d'avance
Aziz
Un développeur tunisien libre :)
Membre enregistré
163 messages
Posté le 20 mars 2017 - 19:56
JeAn-PhI a écrit :


CONSTANTE
SMART_ENABLE_SMART_OPERATIONS = 0xD8
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
FILE_SHARE_READ = 0x1
FILE_SHARE_WRITE = 0x2
OPEN_EXISTING = 0x3
SMART_CYL_LOW = 0x4F
SMART_CYL_HI = 0xC2
IDE_EXECUTE_SMART_FUNCTION = 0xB0
DFP_GET_VERSION = 0x74080
DFP_SEND_DRIVE_COMMAND = 0x7C084
DFP_RECEIVE_DRIVE_DATA = 0x7C088
IDE_ID_FUNCTION = 0XEC
IDENTIFY_BUFFER_SIZE = 512
OUTPUT_DATA_SIZE = IDENTIFY_BUFFER_SIZE + 16
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = 0x560000
FIN

STIDSector est une structure
nGenConfig est un entier SUR 2 octets
nnNumCyls est un entier SUR 2 octets
nReserved est un entier SUR 2 octets
nNumHeads est un entier SUR 2 octets
nBytesPerTrack est un entier SUR 2 octets
nBytesPerSector est un entier SUR 2 octets
nSectorsPerTrack est un entier SUR 2 octets
sfVendorUnique est une chaîne fixe SUR 6
sfSerialNumber est une chaîne fixe SUR 20
nBufferType est un entier SUR 2 octets
nBufferSize est un entier SUR 2 octets
nECCSize est un entier SUR 2 octets
sfFirmwareRev est une chaîne fixe SUR 8
sfModelNumber est une chaîne fixe SUR 40
nMoreVendorUnique est un entier SUR 2 octets
nDoubleWordIO est un entier SUR 2 octets
nCapabilities est un entier SUR 2 octets
nReserved1 est un entier SUR 2 octets
nPIOTiming est un entier SUR 2 octets
nDMATiming est un entier SUR 2 octets
nBS est un entier SUR 2 octets
nNumCurrentCyls est un entier SUR 2 octets
nNumCurrentHeads est un entier SUR 2 octets
nNumCurrentSectorsPerTrack est un entier SUR 2 octets
nCurrentSectorCapacity est un entier SUR 4 octets
nMultSectorStuff est un entier SUR 2 octets
nTotalAddressableSectors est un entier SUR 4 octets
nSingleWordDMA est un entier SUR 2 octets
nMultiWordDMA est un entier SUR 2 octets
sfReserved est une chaîne fixe SUR 128
FIN

.......................... etc ...
--
Cordialement JeAn-PhI


Bonsoir ,
un seul mot , bravo .... encore d'actualité
Posté le 21 mars 2017 - 19:08
Bonsoir,
Il existe une méthode simple pour récupérer numéro de série de la carte mère, numéro de série usine du disque dur et la/les adr mac . En utilisant une partie de ces différents numéros je génère une clé qui est donc liée à ces trois numéros. A partir de cette clé je génère avec un autre logiciel une licence que l'utilisateur saisi. A l'ouverture du logiciel si au moins deux numéros de séries sur les trois sont identifié j'autorise l'ouverture du programme.
Si ce procédé vous intéresse je peux mettre le code en ligne sachant que je me suis inspiré d'informations trouvées sur le site de PCSOFT.
Membre enregistré
28 messages
Posté le 21 mars 2017 - 23:06
bonsoir phyl_501, votre code m'interresse. Pouvez-vous le partager svp.
merci
Posté le 22 mars 2017 - 09:59
Bonjour,
Je suis aussi intéressé de vote code
MErci d'avance
Posté le 22 mars 2017 - 20:26
Bonsoir
Voici déjà la procédure
Procedure RécupèreInfosLicence()
// Extraction d'informations pour gestion Licence
InfoLicence est une structure
NumSérieDisque est une chaîne
NumMacAdresse est une chaîne
NumSérieCarteMère est une chaîne
FIN
 
objLocator est un objet automation "WbemScripting.SWbemLocator"
objService est un objet automation dynamique
Resultats est un objet automation dynamique
MonInfoLicence est une InfoLicence
 
QUAND EXCEPTIONEXCEPTION DANS
objService = objLocator>>ConnectServer(".", "root\cimv2")
objService>>Security_>>ImpersonationLevel = 3
 
// Récupération du numéro de série du 1er disque
Resultats = objService>>ExecQuery("SELECT SerialNumber,Tag FROM Win32_PhysicalMedia WHERE Tag LIKE '%PHYSICALDRIVE0'")
POUR x = 0 _A_ Resultats>>Count -1
MonInfoLicence.NumSérieDisque = Resultats>>ItemIndex(x)>>Properties_>>Item("SerialNumber")>>Value
FIN

// Récupération adresse MAC
Resultats = objService>>ExecQuery("SELECT MACAddress,PhysicalAdapter FROM Win32_NetworkAdapter WHERE PhysicalAdapter=True")
POUR x = 0 _A_ Resultats>>Count -1
SI MonInfoLicence.NumMacAdresse="" ALORS
MonInfoLicence.NumMacAdresse = Resultats>>ItemIndex(x)>>Properties_>>Item("MACAddress")>>Value
SINON
MonInfoLicence.NumMacAdresse += RC+Resultats>>ItemIndex(x)>>Properties_>>Item("MACAddress")>>Value

FIN
FIN

// Récupération du numéro de série de carte mère
Resultats = objService>>ExecQuery("SELECT SerialNumber,Product FROM Win32_BaseBoard")
POUR x = 0 _A_ Resultats>>Count -1
MonInfoLicence.NumSérieCarteMère = Resultats>>ItemIndex(x)>>Properties_>>Item("SerialNumber")>>Value
FIN
FAIRE
Erreur("Erreur execution WMI",ExceptionInfo(errInfo))
ExceptionActive()
RENVOYER "Erreur WMI"
FIN
RENVOYER(MonInfoLicence)


J'ai trouvé ce code dans le forum et je l'ai un peu épuré pour ne garder que ce qui m'intéressait.
Il suffit après d'appeler cette procédure et en retour de traiter les informations.

InfoLicence est une Structure
NumSérieDisque est une chaîne
NumMacAdresse est une chaîne
NumSérieCarteMère est une chaîne
FIN
MonInfoLicence est une InfoLicence

MonInfoLicence=RécupèreInfosLicence()

Après j'utilise une partie des informations que je chiffre et que j'utilise pour générer un clé avec l'instruction "CléGénèreCléInitiale"
Posté le 23 mars 2017 - 14:51
Bjr,

Phyl_501 avait soumis l'idée :
Bonsoir,
Il existe une méthode simple pour récupérer numéro de série de la carte mère,
numéro de série usine du disque dur et la/les adr mac . En utilisant une
partie de ces différents numéros je génère une clé qui est donc liée à ces
trois numéros. A partir de cette clé je génère avec un autre logiciel une
licence que l'utilisateur saisi. A l'ouverture du logiciel si au moins deux
numéros de séries sur les trois sont identifié j'autorise l'ouverture du
programme.
Si ce procédé vous intéresse je peux mettre le code en ligne sachant que je
me suis inspiré d'informations trouvées sur le site de PCSOFT.


Tes clients ne peuvent donc pas changer d'ordinateur ? et ils sont
contents ???

Perso, mon systeme de controle de licence se base sur une combinaison
des enregistrements des fichiers... plus cool je trouve. (MAis je ne
peux pas verouiler un jeu ou autre appli similaire)

a plus

--
-------------------------------------------------------------
www.ctc-soft.com
Gestion biblo-documentaire (free-share)
Comptabilité shareware
Logiciels de Gestion de saisie terrain
Spécialisé Tournées de boulangers
-------------------------------------------------------------
Posté le 23 mars 2017 - 17:55
Bonsoir,
Mes clients peuvent changer une des trois pièces contrôlées (carte mère ou disque dur ou carte réseau) car mon test reste valide si au moins deux des trois éléments sont trouvés à l'ouverture du programme.
S'il change d'ordinateur, j'ai mis en place une génération d'un code de suppression de licence par le client qu'il m'envoie, cela prouve qu'il a supprimé la licence, et je lui renvoie une nouvelle licence liée à sa nouvelle clé.
Posté le 24 mars 2017 - 14:39
et comme fais-tu pour bloquer le poste sur lequel la licence a été
supprimée ?

merci,
eric l.

Le 23/03/2017 à 16:55, Phyl_501 a écrit :
Bonsoir,
Mes clients peuvent changer une des trois pièces contrôlées (carte mère
ou disque dur ou carte réseau) car mon test reste valide si au moins
deux des trois éléments sont trouvés à l'ouverture du programme.
S'il change d'ordinateur, j'ai mis en place une génération d'un code de
suppression de licence par le client qu'il m'envoie, cela prouve qu'il a
supprimé la licence, et je lui renvoie une nouvelle licence liée à sa
nouvelle clé.
Posté le 24 mars 2017 - 16:27
Les licences sont cryptées dans un fichier de la base de données chez le client.
Ce que je n'ai pas dit c'est qu'en plus de la licence je n'active le logiciel chez le client que pour une durée définie. S'il continue à payer sa mensualité, il reçoit un fichier chiffré qui permet de repousser la date de l'ensemble de ses licences.
Pour que le client puisse utiliser de façon frauduleuse une licence il faudrait qu'après avoir supprimé cette licence il fasse une restauration de sa base et qu'il demande seulement à ce moment là sa nouvelle licence.
Je n'ai pas intégré de système pour palier à ce risque car j'ai cette notion de durée sur mes licences, donc il l'utiliserait au maximum un mois.
Il serait possible d'intégrer un système pour palier à ce risque en ajoutant dans la nouvelle clé d'activation les infos de l'ancienne licence (N° carte mère...) et lorsque le client active sa nouvelle licence le programme pourrait vérifier qu'aucune licence ne correspond à l'ancien poste.
Membre enregistré
4 messages
Posté le 24 mars 2017 - 17:06
pour info, moi j'ai fait une protection sur clef USB et je lie la protection au numéro de série de la clef
avec le numéro de série de la clef, je génère un code crypté que j'écris sur la même clef
Si la clef est sur l'ordi, le logiciel fonctionne. Je vérifie que la clef est là à chaque procédure d'écriture grosso-modo, du coup mon logiciel est actif en lecture seulement quand la clef usb n'est pas là.
Si le fichier qui est sur la clef est copié sur une autre clef, forcément ça ne fonctionne pas
Voilà si ça peut servir à qqun
Sinon je serai curieux de voir la procédure de suppression de licence que vous avez utilisé (ou au moins le principe)
Aziz
Posté le 25 mars 2017 - 19:00
Bonjour,
Pour mon code de suppression de licence j'utilise simplement une instruction "CléGénèreCléInitiale" en utilisant comme variable le code durée de la licence qui est liée à la licence à supprimer et qui est elle-même liée au matériel.
Posté le 26 mars 2017 - 15:28
Bonjour,

Le 23/03/2017 à 16:55, Phyl_501 a écrit :
S'il change d'ordinateur, j'ai mis en place une génération d'un code de suppression de licence par le client qu'il m'envoie, cela prouve qu'il a supprimé la licence, et je lui renvoie une nouvelle
licence liée à sa nouvelle clé.


Et si tu as arrêté ton activité entre temps, as-tu prévu une solution de repli pour le client ?
Membre enregistré
1 012 messages
Popularité : +11 (13 votes)
Posté le 26 mars 2017 - 17:40
Salut Phyl_501,

Juste un petit conseil, regarde bien que ce soit autoriser de faire cela dans ton Pays.
Je ne sais pas ou tu habites, mais en Belgique c'est punissable par la loi de faire cela

"Ce que je n'ai pas dit c'est qu'en plus de la licence je n'active le logiciel chez le client que pour une durée définie. S'il continue à payer sa mensualité, il reçoit un fichier chiffré qui permet de repousser la date de l'ensemble de ses licences."

Et ça peut se retourner contre toi. (je le faisais également qu'en j'étais jeune)
C'est juste pour info :D

A+
Daryl

--
http://www.concept4u2.com
Posté le 26 mars 2017 - 18:13
En effet, strictement hors la loi dans toute l'union européenne.
Et c'est logique.
Il n'a pas payé, parce qu'il a changé de logiciel (exemple) :
Il doit pouvoir éditer ses stats précédentes et surtout ses anciennes factures.

Perso je suis toujours étonnée de voir l'énergie passée à protéger une appli.
Membre enregistré
1 012 messages
Popularité : +11 (13 votes)
Posté le 27 mars 2017 - 08:53
Salut Christine,

Bon a savoir que c'est dans toute l'union Européenne :merci:

Pour ce qui est de la protection, quand on travaille sur un programme pendant des années parfois, on a pas trop envie que le 1er venu arrive et trouve une parade pour utiliser notre programme gratuitement. Maintenant tous les programmes sont piratable, c'est juste le temps de trouver comment pirater qui deviens plus ou moins long,

@Phyl_501,

En fait c'est le blocage du programme qui est condamné, si tu empêches l'ajout et la modification seulement, on ne peut rien te reprocher tant que ton client puisse toujours voir les infos déjà sauvegardée (qui elle ne t'appartienne pas, mais appartienne à ton client) :).

A+
Daryl

--
http://www.concept4u2.com
Membre enregistré
4 messages
Posté le 27 mars 2017 - 19:51
Merci pour l'info sur les droits et devoirs en tant qu'éditeur de logiciel. Pour l'instant mon logiciel est seulement en phase de test chez un premier client. Je vais modifier ma protection pour que le client garde un droit de lecture sur ses données.
Encore merci pour l'info.
Membre enregistré
1 012 messages
Popularité : +11 (13 votes)
Posté le 28 mars 2017 - 20:05
Salut Phyl_501,

Avec plaisir 8)
Comme quoi il faut toujours bien se renseigner, surtout que tu peux avoir un cas ou pour un pays ce sera légal et pas pour un autre.

Bon dev et bonnes ventes ;)

A+
Daryl

--
http://www.concept4u2.com
Membre enregistré
4 messages
Posté le 29 mars 2017 - 11:23
Même si ce n'était pas la loi, ça reste logique de laisser un accès en lecture.

--
Aziz T.
Tunis
Windev 12
Posté le 01 avril 2017 - 10:03
GAD a utilisé son clavier pour écrire :
JeAn-PhI a écrit :


CONSTANTE
SMART_ENABLE_SMART_OPERATIONS = 0xD8
GENERIC_READ = 0x80000000
GENERIC_WRITE = 0x40000000
FILE_SHARE_READ = 0x1
FILE_SHARE_WRITE = 0x2
OPEN_EXISTING = 0x3
SMART_CYL_LOW = 0x4F
SMART_CYL_HI = 0xC2
IDE_EXECUTE_SMART_FUNCTION = 0xB0
DFP_GET_VERSION = 0x74080
DFP_SEND_DRIVE_COMMAND = 0x7C084
DFP_RECEIVE_DRIVE_DATA = 0x7C088
IDE_ID_FUNCTION = 0XEC
IDENTIFY_BUFFER_SIZE = 512
OUTPUT_DATA_SIZE = IDENTIFY_BUFFER_SIZE + 16
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = 0x560000
FIN

STIDSector est une structure
nGenConfig est un entier SUR 2 octets
nnNumCyls est un entier SUR 2 octets
nReserved est un entier SUR 2 octets
nNumHeads est un entier SUR 2 octets
nBytesPerTrack est un entier SUR 2 octets
nBytesPerSector est un entier SUR 2 octets
nSectorsPerTrack est un entier SUR 2 octets
sfVendorUnique est une chaîne fixe SUR 6
sfSerialNumber est une chaîne fixe SUR 20
nBufferType est un entier SUR 2 octets
nBufferSize est un entier SUR 2 octets
nECCSize est un entier SUR 2 octets
sfFirmwareRev est une chaîne fixe SUR 8
sfModelNumber est une chaîne fixe SUR 40
nMoreVendorUnique est un entier SUR 2 octets
nDoubleWordIO est un entier SUR 2 octets
nCapabilities est un entier SUR 2 octets
nReserved1 est un entier SUR 2 octets
nPIOTiming est un entier SUR 2 octets
nDMATiming est un entier SUR 2 octets
nBS est un entier SUR 2 octets
nNumCurrentCyls est un entier SUR 2 octets
nNumCurrentHeads est un entier SUR 2 octets
nNumCurrentSectorsPerTrack est un entier SUR 2 octets
nCurrentSectorCapacity est un entier SUR 4 octets
nMultSectorStuff est un entier SUR 2 octets
nTotalAddressableSectors est un entier SUR 4 octets
nSingleWordDMA est un entier SUR 2 octets
nMultiWordDMA est un entier SUR 2 octets
sfReserved est une chaîne fixe SUR 128
FIN
......................... etc ...

--
Cordialement JeAn-PhI

Bonsoir ,
un seul mot , bravo .... encore d'actualité


Oui et vous avez demandé à Orange ou Sfr de vous laisser utiliser votre
telephone apres avoir fini de payer vos mensualités ?
ils ont accepté j'espere ?

a plus

--
-------------------------------------------------------------
www.ctc-soft.com
Gestion biblo-documentaire (free-share)
Comptabilité shareware
Logiciels de Gestion de saisie terrain
Spécialisé Tournées de boulangers
-------------------------------------------------------------